home *** CD-ROM | disk | FTP | other *** search
/ Aminet 21 / Aminet 21 (1997)(GTI - Schatztruhe)[!][Oct 1997].iso / Aminet / dev / c / FW_ACMint.lha / ACE-Intuition (.txt) < prev   
Encoding:
Final Write Document  |  1997-07-18  |  635.7 KB  |  7,441 lines

  1. Chapter 1 "SCREENS"
  2.  
  3. 1.1  Introduction
  4. 1.2  Different Types of Screens
  5. 1.3  Workbench Screen
  6. 1.4  Custom Screens
  7. 1.4.1  Resolution
  8. 1.4.2  Depth
  9. 1.4.3  Interlace
  10. 1.4.4  HAM and Extra HalfBrite
  11. 1.4.5  Dual Playfields
  12. 1.4.6  Fonts
  13. 1.4.7  Size and Position
  14. 1.4.8  Title
  15. 1.4.9  Gadgets
  16. 1.5  Iinitialize a Cuztom Screen
  17. 1.6  Open a Custom Screen
  18. 1.7  Screen Structure
  19. 1.8  Functions
  20. 1.9  Examples
  21.  
  22. Chapter 2 "WINDOWS"
  23.  
  24. 2.1  Introduction
  25. 2.2  Special Windows
  26. 2.2.1  Backdrop Windows
  27. 2.2.2  Borderless Windows
  28. 2.2.3  GimmeZeroZero Windows
  29. 2.2.4  Superbitmap Windows
  30. 2.3  System Gadgets
  31. 2.4  Redrawing the Window Display
  32. 2.5  Initialize a Window
  33. 2.6  Open a Window
  34. 2.7  Window Structure
  35. 2.8  Open a Superbitmap Window
  36. 2.9  Make Your Own custom Pointer
  37. 2.10  Functions
  38. 2.11  Examples
  39.  
  40. Chapter 3 "GRAPHICS"
  41.  
  42. 3.1  Introduction
  43. 3.2  Lines Text Pictures
  44. 3.3  Borders
  45. 3.3.1  The Border Structure
  46. 3.3.2  Coordinates
  47. 3.4 How to Use the Border Structure
  48. 3.4  Text
  49. 3.4.1  The Intuitext Structure
  50. 3.4.2  Fonts
  51. 3.4.3  How to Use the Intuitext Structure
  52. 3.5  Images
  53. 3.5.1  Image Data
  54. 3.5.2  The Image Structure
  55. 3.5.3  PlanePick
  56. 3.5.4  PlaneOnOff
  57. 3.5.5  How to Use the Image Structure
  58. 3.6  Functions
  59. 3.7  Examples
  60.  
  61. Chapter 4 "GADGETS"
  62.  
  63. 4.1  Introduction
  64. 4.2  Different Types of Gadgets
  65. 4.3  Custom Gadgets
  66. 4.3.1  Graphics for Custom Gadgets
  67. 4.3.2  Position
  68. 4.3.3  Size
  69. 4.4  Initialize a Custom Gadget
  70. 4.5  Boolean Gadget
  71. 4.6  String/Integer Gadget
  72. 4.6.1  StringInfo Structure
  73. 4.6.2  Initialize a String/Integer Gadget
  74. 4.6.3  Usign a String/Integer Gadget
  75. 4.7  Proportional Gadget
  76. 4.7.1  PropInfo Structure
  77. 4.7.2  Initialize a Proportional Gadget
  78. 4.8  Monitoring the Gadgets
  79. 4.9  Functions
  80. 4.10  Examples
  81.  
  82. Chapter 5 "REQUESTERS"
  83.  
  84. 5.1  Introduction
  85. 5.2  Different Types of Requesters
  86. 5.2.1  System Requesters
  87. 5.2.2  Application Requesters
  88. 5.2.3  Double-Menu Requesters
  89. 5.3  Graphics for Requesters
  90. 5.4  Position
  91. 5.5  Requesters andGadgets
  92. 5.6  Simple Requesters
  93. 5.7  Open a Requester
  94. 5.7.1  Initialize a Requester
  95. 5.7.2  How to Activate an Application Requester
  96. 5.8  IDCMP Flags
  97. 5.9  Functions
  98. 5.10  Examples
  99.  
  100. Chapter 6 "ALERTS"
  101.  
  102. 6.1  Introduction
  103. 6.2  Different Levels of Warnings
  104. 6.3  How to Use the DisplayAlert() Function
  105. 6.4  Examples of Strings and Substrings
  106. 6.5  Functions
  107. 6.6  Examples
  108.  
  109. Chapter 7 "MENUS"
  110.  
  111. 7.1  Introduction
  112. 7.2  Menu Design
  113. 7.3  How to Access Menus From the Keyboard
  114. 7.4  Menu Items
  115. 7.5  Mutual Exclude
  116. 7.6  Open a Menu
  117. 7.6.1  Initialize a Menu Structure
  118. 7.6.2  Initialize a MenuItem Structure
  119. 7.6.3  How to Submit and Remove a Menu Strip To/From a Window
  120. 7.7  Special IDCMP Flags
  121. 7.7.1  MenuPick
  122. 7.7.2  MenuVerify
  123. 7.8  Menu Nubers
  124. 7.9  Functions
  125. 7.10  Macros
  126. 7.11  Examples
  127.  
  128. Chapter 8 "IDCMP"
  129.  
  130. 8.1  Introduction
  131. 8.2  IDCMP Ports
  132. 8.3  How to Recieve IDCMP Messages
  133. 8.3.1  Open IDCMP Ports
  134. 8.3.2  Wait for Messages
  135. 8.3.3  Collect Messages
  136. 8.3.4  Examine the Message
  137. 8.3.5  Reply
  138. 8.3.6  Example
  139. 8.4  IDCMP Flags
  140. 8.5  Functions
  141. 8.6  Examples
  142.  
  143. Chapter 9 "MISCELLANEOUS"
  144.  
  145. 9.1  Introduction
  146. 9.2  Memory
  147. 9.2.1  Allocate Memory
  148. 9.2.2  Deallocate Memory
  149. 9.2.3  Remember Memory
  150. 9.3  Preferences
  151. 9.4  Warnings
  152. 9.5  Double Click
  153. 9.6  Time
  154. 9.7  Style
  155. 9.7.1  Gadgets
  156. 9.7.2  Requesters
  157. 9.7.3  Menus
  158. 9.7.4  Mouse
  159. 9.8  Functions
  160. 9.9  Examples
  161.  
  162. Chapter 10 "File Window"
  163.  
  164. Chapter 11 "Colour Window"
  165. TABLE OF CONTENTS
  166.  
  167. SCREENS
  168.  
  169. 1.1  INTRODUCTION
  170.  
  171. The screen is the foundation of Intuition's display. It determines how many 
  172. colours you can use, what kind of colours, what resolution etc. Every window, 
  173. gadget, icon, drawing is connected to a screen. Moving that screen, and you are 
  174. also moving the objects on it. You may have several screens running at the same 
  175. time, and you may combine different screens (with their own individual 
  176. resolutions, colours, etc) on the same display.
  177.  
  178. In this chapter we will only look at the "standard screens" which all Amiga 
  179. models support. There exist new models like the Amiga 3000 which can use new 
  180. types screens with different sizes and limitations. Since only some models 
  181. support these new modes there will be a special chapter about this.
  182.  
  183. What is described in the following chapters will work on all Amiga models.
  184.  
  185. 1.2  DIFFERENT TYPES OF SCREENS
  186.  
  187. When you are going to use a screen you first need to decide if you want to use 
  188. a Standard (Workbench) Screen or if you want to use a Screen which you yourself 
  189. have customized (Custom Screens).
  190.  
  191. Workbench Screen:
  192. This is Intuition's standard screen. It is a four-colour,   high-resolution 
  193. screen. 
  194.  
  195. Custom Screens:
  196. When you want a screen with your own display mode you should use a Custom 
  197. Screen. You can then decide yourself how many colours you want, what colours, 
  198. resolution, size etc.
  199.  
  200. If your program should use a high-resolution screen, and four colours is 
  201. enough, you are advised to use the Workbench Screen. This will save a lot of 
  202. memory (no memory allocated for a Custom Screen), and allows the user to have 
  203. several programs running on the same display. On the other hand, if you want
  204. more colours or want to use a different resolution/display-mode you should use 
  205. a Custom Screen.
  206.  
  207. 1.3  WORKBENCH SCREEN
  208.  
  209. Workbench Screen is a high-resolution (640 pixels wide), four colour screen. It 
  210. is either 200 or 256 lines high depending on if you have a NTSC (American) or a 
  211. PAL (European) computer. (400/512 lines if you have an Interlaced display.)
  212.  
  213. The Workbench Screen will automatically open if there does not exist any other 
  214. screens. If you do not want the Workbench Screen, and need a lot of memory, you 
  215. can try to close it, CloseWorkBench(). Remember to reopen it when your program 
  216. has finished, OpenWorkBench().
  217.  
  218. You are advised to always call the function OpenWorkBench() when your program 
  219. exits, even if you have not closed it yourself. Another program may have closed 
  220. it because of shortage of memory, and when your program is finished there may 
  221. exist enough memory. This will make the Workbench Screen
  222. available as much as possible.
  223.  
  224. 1.4  CUSTOM SCREENS
  225.  
  226. If you are going to use a Custom Screen you need to initialize a structure 
  227. (NewScreen) with your requirements. You also need to open the screen yourself 
  228. by calling the function OpenScreen().
  229.  
  230. Here is a list of some important decisions you need to make before you can open 
  231. the screen:
  232.   
  233. 1.4.1  RESOLUTION
  234.  
  235. You can either have a high-resolution or a low-resolution screen. A high 
  236. resolution screen is 640 pixels wide, while a low-resolution screen is only 320 
  237. pixels wide. However, a high- resolution screen may only have a depth of up to 
  238. 4 (maximum 16 colours), while a low-resolution screen may have a depth of up
  239. to 5 (32 colours), or even 6 if using some special display modes.
  240.  
  241. 1.4.2  DEPTH
  242.  
  243. A screen's depth means how many bits are used for every pixel. The more bits 
  244. the more combinations/colours:
  245.  
  246. Depth
  247.     
  248. Number of
  249.     
  250. Colour register 
  251.     
  252.   colours 
  253.     
  254.     number
  255. --------------------------------------------------
  256.   1             2  
  257.     
  258.     
  259.       0 -  1
  260.   2             4                
  261.     
  262.       0 -  3
  263.   3             8      
  264.     
  265.     
  266.       0 -  7
  267.   4            16       
  268.     
  269.       0 - 15
  270.   5            32          
  271.     
  272.       0 - 31  (Only low-res)
  273.  
  274. A low resolution screen may even have a depth of 6 if using some special 
  275. display modes (HAM / EXTRA HALFBRIGHTE ).
  276.  
  277. Each colour may be picked out of a 4096 colour palette. Once you have opened 
  278. your Custom Screen you may change the colours by calling the graphics function 
  279. SetRGB4().
  280.  
  281. 1.4.3  INTERLACED
  282.  
  283. An Interlaced screen can be 400/512 lines while a Non-Interlaced screen can 
  284. only be 200/256 lines. You are recommended to use a Non-Interlaced screen if 
  285. possible, since an Interlaced display appear to "flicker" if the user does not 
  286. have a special high-phosphor-persistence monitor. (99% of the users do not
  287. have it.)
  288.  
  289. The monitor normally draws the display 50 times per second. If you are using an 
  290. Interlaced screen the Amiga will only draw every second line first, and will 
  291. the next time draw the remaining lines. This is why an Interlaced display 
  292. appear to "flicker". You can eliminate much of the disturbing effects if you 
  293. are using colours with low contrasts, black and grey instead of black and white 
  294. for example.
  295.  
  296. 1.4.4  HAM AND EXTRA HALFBRIGHTE
  297.  
  298. If you have a low-resolution, six bitplanes (Depth 6) screen you can either use 
  299. the special HAM mode, or the Extra Halfbrighte mode. HAM allows you to display 
  300. all 4096 colours at the same time, but has some restrictions, and is 
  301. complicated to use. Extra Halfbrighte gives you 32 extra colours, which are the 
  302. same as the first 32 colours, but are a bit brighter.
  303.  
  304. Both HAM and Extra Halfbrighte is using a lot of memory/processing time, and is 
  305. therefore not commonly used.
  306.  
  307.  
  308. 1.4.5  DUAL PLAYFIELDS
  309.  
  310. Dual Playfields allows you to have two screens on top of each other. The top 
  311. screen can then be transparent in some places (colour register 0) to show the 
  312. bottom screen.
  313.  
  314. 1.4.6  FONTS
  315.  
  316. You can specify a default font which will be used, if nothing else is 
  317. specified, to draw the text on the screen. The system's default font is called 
  318. Topaz and exist in two sizes:
  319.  
  320. TOPAZ_SIXTY  : 9 lines tall, 64/32 characters per line.
  321. TOPAZ_EIGHTY : 8 lines tall, 80/40 characters per line.
  322.  
  323. This font is built in the Amiga, and is therefore always available. (See 
  324. chapter 3 GRAPHICS for more information.)
  325.  
  326. 1.4.7  SIZE AND POSITION
  327.  
  328. The top of your screen does not need to be at the top of the display. You may 
  329. open several screens and position them under each other. If you are, for 
  330. example, designing an adventure game, you can have a low-resolution 32 colour 
  331. screen at the top of the display (showing some nice pictures), and have a high-
  332. resolution 2 colour screen at the bottom of the display (showing the text).
  333.  
  334. (Remember that the user later can drag the screens up or down himself.) 
  335.  
  336. The width of the screen should be either 320 (low-resolution) or 640 pixels 
  337. (high-resolution).
  338.  
  339. The height may be anything between 1 - 200/256 lines on an Non- Interlaced 
  340. screen, and between 1 - 400/512 lines on an Interlaced display.
  341.  
  342. 1.4.8  TITLE
  343.  
  344. On top of each screen (on the "drag bar") there exist a screentitle. There 
  345. exist two kinds of titles:
  346.   - The default title, which is specified in the NewScreen structure.
  347.   - A "current" title which is the same as the title of the current active 
  348. window. (See chapter 2 WINDOWS for more information.)
  349.  
  350. 1.4.9  GADGETS
  351.  
  352. For the moment you are not allowed to attach any custom gadgets to a screen. 
  353. (See chapter 4 GADGETS for more information about gadgets.)
  354.  
  355. 1.5  INITIALIZE A CUSTOM SCREEN
  356.  
  357. Before you can open a custom screen you need to initialize a NewScreen 
  358. structure which look like this:
  359.  
  360. struct NewScreen
  361. {
  362.   SHORT LeftEdge, TopEdge, Width, Height, Depth;
  363.   UBYTE DetailPen, BlockPen;
  364.   USHORT ViewModes;
  365.   USHORT Type;
  366.   struct TextAttr *Font;
  367.   UBYTE *DefaultTitle;
  368.   struct Gadget *Gadgets;
  369.   struct BitMap *CustomBitMap;
  370. };
  371.  
  372. LeftEdge:
  373.     
  374. Initial x position of the screen. Should always be 0.
  375.  
  376. TopEdge:
  377.     
  378. Initial y position of the screen.
  379.  
  380. Width:
  381.     
  382. If it is a low-resolution screen it should be 320, otherwise 640.
  383.  
  384. Height:
  385.     
  386. If it is a Non-Interlaced screen it can be anything between 1 - 200/256, 
  387. otherwise 1 - 400/512.
  388.  
  389. Depth:
  390.     
  391. 1-4 if high-resolution, otherwise 1-6.
  392.  
  393. DetailPen:
  394.     
  395. The colour register used to draw the text with.
  396.  
  397. BlockPen:
  398.     
  399. The colour register used for block fills etc.
  400.  
  401. ViewModes:
  402.     
  403. You can use none or some of the flags. If you set more than one flag you put a 
  404. "|" between them. (You are not allowed to set the HIRES flag together with the 
  405. DUALPF or HAM flag, and you can not have DUALPF at the same time as HAM.)
  406.  
  407. HIRES
  408.     
  409. Set this flag if you want a high- resolution screen. (The default is 
  410. low-resolution.)
  411.  
  412. INTERLACE
  413.     
  414. Set this flag if you want an  Interlaced screen. (The default is 
  415. Non-Interlaced)
  416.  
  417. SPRITES
  418.     
  419. Set this flag if you are going to use sprites in your display.
  420.  
  421. DUALPF
  422.     
  423. Set this flag if you want to use the Dual Playfields Mode.
  424.  
  425. HAM
  426.     
  427. Set this flag if you want to use the Hold And Modify Mode.
  428.  
  429. Type:
  430.     
  431. Should be CUSTOMSCREEN. You can also set the CUSTOMBITMAP flag if you want the 
  432. screen to use your own declared and initialized BitMap. (See chapter 2 WINDOWS 
  433. for more information about Custom BitMaps.)
  434.  
  435. Font:
  436.     
  437. A pointer to an already initialized TextAttr structure. The screen will use it 
  438. as the default font. (See chapter 3 GRAPHICS for more information about fonts.) 
  439. Set to NULL if you want to use the current default font.
  440.  
  441. DefaultTitle:
  442.     
  443. A pointer to a text string which will be used as "default" title.
  444.  
  445. Gadgets:
  446.     
  447. Not used for the moment. Set to NULL.
  448.  
  449. CustomBitMap:
  450.     
  451. If you want to use your own BitMap you should give this field a pointer to the 
  452. BitMap structure which you have declared, and initialized yourself. Remember to 
  453. set the CUSTOMBITMAP flag in the Type variable. However, if you want Intuition 
  454. to take care of the BitMap, set this field to NULL. (See chapter 2 WINDOWS for 
  455. more information about Custom BitMaps.)
  456.  
  457. 1.6  OPEN A CUSTOM SCREEN
  458.  
  459. Once you have declared and initialized the NewScreen structure, you can call 
  460. the function OpenScreen() which will open your Custom Screen. When your screen 
  461. has been opened you can, if you have allocated memory for the NewScreen 
  462. structure, deallocate it since you do not need the structure any more.
  463.  
  464. This is how you call the OpenScreen() function:
  465.  
  466. my_screen = OpenScreen( &my_new_screen ); 
  467.  
  468. my_screen has been declared as:
  469.   
  470. struct Screen *my_screen;
  471.  
  472. my_new_screen has been declared as:
  473.   
  474. struct NewScreen my_new_screen;
  475.   and has been initialized with your requirements.
  476.  
  477.  
  478. OpenScreen() will return a pointer to a Screen structure, else
  479. NULL if it could not open the screen (for example, not enough
  480. memory). Remember to check what OpenScreen() returned!
  481.  
  482. if( my_screen==NULL )
  483. {
  484.   /* PANIC! Could not open the screen */
  485. }
  486.  
  487. 1.7  SCREEN STRUCTURE
  488.  
  489. Once you have opened the screen you will receive a pointer to a Screen 
  490. structure which look like this:
  491.  
  492. struct Screen
  493. {
  494.   struct Screen *NextScreen;    /* Pointer to the next */
  495.                                 /* screen, or NULL. */
  496.   struct Window *FirstWindow;   /* Pointer to the first */
  497.                                 /* Window on this screen. */
  498.   SHORT LeftEdge, TopEdge;      /* Position of the screen. */
  499.   SHORT Width, Height;          /* Size of the screen. */
  500.   SHORT MouseY, MouseX;         /* Mouse position relative */
  501.                                 /* to the top left corner */
  502.                                 /* of the screen. */
  503.   USHORT Flags;                 /* The selected flags. */
  504.   UBYTE *Title;                 /* The screen's Current title. */
  505.   UBYTE *DefaultTitle;          /* The screen's Default title. */
  506.  
  507.   BYTE BarHeight, BarVBorder,
  508.        BarHBorder, MenuVBorder,
  509.        MenuHBorder;
  510.   BYTE WBorTop, WBorLeft,
  511.        WBorRight, WBorBottom;
  512.  
  513.   struct TextAttr *Font;        /* The screens default font. */
  514.   struct ViewPort ViewPort;     /* The screen's ViewPort etc: */
  515.   struct RastPort RastPort;
  516.   struct BitMap BitMap;
  517.   struct Layer_Info LayerInfo;
  518.   struct Gadget *FirstGadget;
  519.   UBYTE DetailPen, BlockPen;
  520.   USHORT SaveColor0;
  521.   struct Layer *BarLayer;
  522.   UBYTE *ExtData;
  523.   UBYTE *UserData;
  524. };
  525.  
  526. You will probably not use this structure a lot, but some variables/structures 
  527. can be useful later on. When you are, for example, using the function 
  528. SetRGB4(). More about this later.
  529.  
  530. 1.8  FUNCTIONS
  531.  
  532. Here are some common functions which will affect screens:
  533.  
  534. OpenScreen()
  535.  
  536. This function will open a Custom Screen with your requirements.
  537.  
  538. Synopsis
  539. :      
  540. my_screen = OpenScreen( my_new_screen );
  541.   
  542. my_screen:
  543.     
  544. (struct Screen *) Pointer to a Screen structure. It will point to your newly 
  545. opened screen or be equal to NULL if the screen could not be opened.
  546.  
  547. my_new_screen:
  548.     
  549. (struct NewScreen *) Pointer to a NewScreen structure which contains your 
  550. preferences.
  551.  
  552. CloseScreen()
  553.  
  554. This function will close a Custom Screen which you have previously opened.
  555.   
  556. Synopsis:      
  557. CloseScreen( my_screen );
  558.   
  559. my_screen:
  560.     
  561. (struct Screen *) Pointer to an already opened screen.
  562.  
  563. All windows (See chapter 2 WINDOWS for more information) on your Screen MUST 
  564. have been closed before you may close the screen. If you close a window after 
  565. the screen has been
  566. closed, the system will crash. (Not recommended.)
  567.   
  568. If there does not exist any more screens when you close yours, Intuition will 
  569. automatically reopen the Workbench Screen.
  570.  
  571. MoveScreen()
  572.  
  573. This function will move the screen. For the moment you may
  574. only move it vertically.
  575.  
  576. Synopsis:      
  577. MoveScreen( my_screen, delta_x, delta_y );
  578.  
  579. my_screen:
  580.     
  581. (struct Screen *) Pointer to the screen which you want to move.
  582.  
  583. delta_x:
  584.     
  585. (long) Number of pixels which the screen should move horizontally. For the 
  586. moment you may not move a screen horizontally, set it therefore to 0.
  587.  
  588. delta_y:
  589.     
  590. (long) Number of lines which the screen should move vertically.
  591.  
  592. ScreenToBack()
  593.  
  594. This will move the screen behind all other screens.
  595.   
  596. Synopsis:      
  597. ScreenToBack( my_screen );
  598.  
  599. my_screen:
  600.     
  601. (struct Screen *) Pointer to the screen which you want to move.
  602.  
  603. ScreenToFront()
  604.  
  605. This will move the screen in front of all other screens.
  606.   
  607. Synopsis:      
  608. ScreenToFront( my_screen );
  609.  
  610. my_screen:
  611.     
  612. (struct Screen *) Pointer to the screen which you want to move.
  613.  
  614. ShowTitle()
  615.  
  616. This function will make the screen's Title appear above or behind any Backdrop 
  617. Windows (See chapter 2 WINDOWS for more information about Backdrop Windows). 
  618. (The screen's title appear always behind normal windows.)
  619.  
  620. Synopsis:      ShowTitle( my_screen, show_it );
  621.  
  622. my_screen:
  623.     
  624. (struct Screen *) Pointer to the screen.
  625.  
  626. show_it:
  627.     
  628. (long) A boolean value which can be:
  629.     
  630. TRUE: The title will be in front of any Backdrop Windows, but behind any other 
  631. windows.
  632.     
  633. FALSE: The Title will be behind any windows.
  634.  
  635. OpenWorkBench()
  636.  
  637. This function will try to open the Workbench Screen if there exist enough 
  638. memory.
  639.   
  640. Synopsis:      
  641. result = OpenWorkBench();
  642.   
  643. result:
  644.     
  645. (long) A boolean value which tell us if the Workbench Screen has been (or 
  646. already was) opened (TRUE), or not (FALSE).
  647.  
  648. CloseWorkBench()
  649.  
  650. This function will try to close the Workbench Screen if possible. If any other 
  651. programs is using the Workbench Screen, the function can not close it. Closing 
  652. the Workbench will free some memory, and can therefore be used if your program 
  653. needs more memory.
  654.   
  655. (Remember to reopen the Workbench Screen when your program  terminates.)
  656.  
  657. Synopsis:      
  658. result = CloseWorkBench();
  659.   
  660. result:
  661.     
  662. (long) A boolean value which tell us if the Workbench screen has been (or 
  663. already was) closed (TRUE), or not (FALSE).
  664.  
  665. WBenchToBack()
  666.  
  667. This will move the Workbench Screen behind all other screens.
  668.   
  669. Synopsis:      
  670. result = WBenchToBack();
  671.  
  672. result:
  673.     
  674. (long) A boolean value which is TRUE if the Workbench screen was open, or FALSE 
  675. it it was not.
  676.  
  677. WBenchToFront()
  678.  
  679. This will move the Workbench Screen in front of all other screens.
  680.  
  681. Synopsis:      
  682. result = WBenchToFront();
  683.  
  684. result:
  685.     
  686. (long) A boolean value which is TRUE if the Workbench screen was open, or FALSE 
  687. it it was not.
  688.  
  689. SetRGB4()
  690.  
  691. This function allows you to change your screen's colours. Each colour may be 
  692. picked out of a 4096 colour palette. (16 levels of red, 16 levels of green and 
  693. 16 levels of blue; 16*16*16 = 4096.)
  694.  
  695. IMPORTANT! Before you may use this function you must have opened the Graphics 
  696. Library. (All other functions are in the Intuition Library.) (See chapter 0 
  697. INTRODUCTION for more information.)
  698.  
  699. Synopsis:   
  700. SetRGB4( viewport, register, red, green, blue );
  701.            
  702. viewport:
  703.     
  704. (struct ViewPort *) Pointer to a ViewPort which colour registers we are going 
  705. to change. We can find the screen's ViewPort in the Screen structure. (If 
  706. my_screen is a pointer to a Screen structure, this will get us a pointer to 
  707. that screen's ViewPort: &my_screen->ViewPort)
  708.  
  709. register:
  710.     
  711. (long) The colour register you want to change. The screen's Depth decides how 
  712. many colour registers the screen have:
  713.     
  714. Colour 
  715.     
  716. Depth
  717.     
  718. Registers
  719.     
  720. 1
  721.     
  722.     0 - 1
  723.     
  724. 2
  725.     
  726.     0 - 3
  727.     
  728. 3
  729.     
  730.     0 - 7
  731.     
  732. 4
  733.     
  734.     0 - 15
  735.     
  736. 5
  737.     
  738.     0 - 31
  739.     
  740. 6
  741.     
  742.     0 - 63
  743.     
  744. red:        Amount of red. (0 - 15)
  745.     
  746. green:      Amount of green. (0 - 15 )
  747.     
  748. blue:       Amount of blue. (0 - 15 )
  749.  
  750.  
  751.     
  752. Eg: SetRGB4( &my_screen->ViewPort, 2, 15, 15, 0 ); will change colour register 
  753. 2 to be light yellow. (Red and green together will be yellow.)
  754.  
  755. 1.9  EXAMPLES
  756.  
  757. We have now talked about different screens, Workbench Screen and your own 
  758. Custom Screens. We have looked at how you can change the Custom Screen's 
  759. display mode, resolution, depth etc, and we have described some important 
  760. functions. It is now time for us to have some examples to clear up any 
  761. confusions.
  762.  
  763. Example 1
  764. This program will open a low-resolution, non-Interlaced, eight colour Custom 
  765. Screen. It will display it for 30 seconds, and then close it.
  766.  
  767. Example 2
  768. Same as Example 1 except that the screen will be a high-resolution, Interlaced, 
  769. 4 colour Custom Screen.
  770.  
  771. Example 3
  772. Same as Example 1 except that we will use the TOPAZ_SIXTY Italic style as 
  773. default font. (See chapter 3 GRAPHICS for more information about text styles.)
  774.  
  775. Example 4
  776. This program will open two screens, one (low-resolution 32 colours) at the top 
  777. of the display, and one (high-resolution 16 colours) a bit down.
  778.  
  779. Example 5
  780. Same as Example 4 except that after 10 seconds the low- resolution screen will 
  781. move down 75 lines. After another 10 seconds it will be put in front of all 
  782. other screens. 10 seconds later it will move down another 75 lines. The program 
  783. will wait 10 seconds before the screens are closed and the program exits.
  784.  
  785. Example 6
  786. This program will open a low-resolution, non-Interlaced, 4 colour Custom 
  787. Screen. It will after 5 seconds start to change the screens colours, and will 
  788. after a while close the screen and exit. 
  789.  
  790.  
  791. WINDOWS
  792.  
  793. 2.1  INTRODUCTION
  794.  
  795. Windows are rectangular boxes which can be as big as the screen or only 1 pixel 
  796. wide. They can be resized, moved around on the screen, put in front or behind 
  797. other windows and so on. All this is taken care of by Intuition, and your 
  798. program does not even need to know about it if you do not want.
  799.  
  800. The aim with Windows is to make the communication between the user and the 
  801. computer as easy as possible. Windows gives the user a structured display which 
  802. is easy to understand. It also allows the user to interact with the programs 
  803. through graphics symbols (gadgets) which can be connected to the windows. (See 
  804. chapter 4 GADGETS for more information about gadgets.)
  805.  
  806. Windows are working close together with screens, since the screen's resolution 
  807. etc affects the way the windows are drawn. Moving a screen will also result in 
  808. moving all the windows connected to that screen.
  809.  
  810. 2.2  SPECIAL WINDOWS
  811.  
  812. The normal windows are rectangular boxes with a border around. However, there 
  813. exist some special types of windows:
  814.  
  815. 2.2.1  BACKDROP WINDOWS
  816.  
  817. Backdrop Windows will always be behind any other windows. This allows you to 
  818. have a window in the bottom of the display, and it will stay there, even if the 
  819. user is using the "depth-arrange gadgets".
  820.  
  821. Backdrop Windows differ from other windows since:
  822.  
  823. - It will always open behind all other windows, including other already opened 
  824. Backdrop Windows.
  825.  
  826. - The "close-window gadget" is the only System Gadget you can attach to a 
  827. Backdrop Window. (You can of course attach your own gadgets as usual.)
  828.  
  829. - It will always be behind any other windows. 
  830.  
  831. The Backdrop Window is very handy when you want to have a bottom drawing (for 
  832. example your main display), with some tools etc on top of the bottom window. 
  833. This allows the user to move around your tools as he/she wants without needing 
  834. to worry about hiding the windows behind the main display.
  835.  
  836. Drawing into a Backdrop Window instead of the screen itself is very common 
  837. since you can then not draw anything at the wrong moment. If a menu (See 
  838. chapter 5 MENUS for more information) is displayed, the drawing routines will 
  839. wait automatically, and will therefore not destroy the menu, as it would have 
  840. happened if you were drawing directly into the screen.
  841.  
  842. 2.2.2  BORDERLESS WINDOWS
  843.  
  844. Borderless windows are as normal windows except that they (surprise, surprise) 
  845. do not have any borders. It is very common to combine a Borderless window with 
  846. a Backdrop window, to cover a screen.
  847.  
  848. It can be confusing for the user if a Borderless window does not cover the 
  849. entire display, since he/she will not be able to see where the window's edges 
  850. are. It is therefore normally best to make a Borderless window as big as the 
  851. screen.
  852. 2.2.3  GIMMEZEROZERO WINDOWS
  853.  
  854. A Gimmezerozero Window is as a normal window, except that it consist of two 
  855. drawing areas: one Outer and one Inner window. The Outer window is used for 
  856. displaying the borders, system gadgets etc, while the Inner window is only used 
  857. by yourself.
  858.  
  859. If you are drawing into a normal window you need to start some pixels down/out 
  860. (11, 1), so you do not draw into the borders etc. However, if you are drawing 
  861. into a Gimmezerozero Window you do not need to make any adjustments. The top 
  862. left corner of your inner window is always at the position (0,0).
  863.  
  864. Gimmezerozero Windows are therefore very handy if you want to make a lot of 
  865. drawings, without wanting to worry about the borders. The disadvantages is that 
  866. it takes more memory and processing time than a normal window.
  867.  
  868. 2.2.4  SUPERBITMAP WINDOWS
  869.  
  870. If you are using a SuperBitMap Window you allocate display memory yourself for 
  871. the window instead of letting Intuition take care of it. The advantage is that 
  872. you can define a larger drawing area than the size of the window. You can then 
  873. scroll the drawing area inside the window. A good example of this are the demo 
  874. programs that followed with you Workbench disk when you bought your computer.
  875.  
  876. It normally best to combine a SuperBitMap Window together with a Gimmezerozero 
  877. Window. The borders etc will then NOT be drawn into your SuperBitMap, and will 
  878. instead be drawn in the Outer window. This allows you to make whatever you want 
  879. with the inner window without destroying any borders etc.
  880.  
  881. 2.3  SYSTEM GADGETS
  882.  
  883. The System Gadgets enables the user to move the window, resize it, push it 
  884. behind other windows etc, without your program even knowing about it. The 
  885. System Gadgets are controlled by Intuition, and are always looking the same. 
  886. The only thing you need to do is to tell Intuition which gadgets you want, and 
  887. the rest is done for you.
  888.  
  889. The five System Gadgets are placed like this:
  890.  
  891.  1       2       3  4
  892. [*][***********][*][*]
  893. |                    |
  894. |       WINDOW       |
  895. |                    |
  896. |                    |
  897. |__________________[*]
  898.                     5
  899.  
  900. 1  Close Gadget. Press this to close the window. (This is the only System 
  901. Gadget which your program have to respond to. Your program will be told that 
  902. the user has clicked on the Close Gadget, but you need to close the window 
  903. yourself by calling the function CloseWindow().)
  904.  
  905. 2  Drag Gadget. Pressing the left mouse button somewhere on it and move the 
  906. mouse while the button is still pressed, will move the window. If your window 
  907. has a title it will be displayed over the Drag Gadget, but will not interfere 
  908. with it.
  909.  
  910. 3  Depth-Arrangement Gadget BACK. Clicking on this gadget will push the window 
  911. behind all other windows.
  912. 4  Depth-Arrangement Gadget UP. Clicking on this gadget will put the window in 
  913. front of all other windows.
  914.  
  915. 5  Sizing Gadget. Pressing the left mouse button somewhere on it and move the 
  916. mouse while the button is still pressed, will change the size of the window.
  917.  
  918. 2.4  REDRAWING THE WINDOW DISPLAY
  919.  
  920. Since windows can be dragged around the screen it is very common that they 
  921. sometimes overlap each other. If the user is then moving away the top window, 
  922. the bottom window has to be refreshed.
  923.  
  924. There exist two methods of redrawing the window:
  925.  
  926. - Simple Refresh. Intuition will only tell you that you need to refresh it, and 
  927. your program has to redraw everything itself.
  928. - Smart Refresh. Intuition saves the obscured pieces, and replaces them 
  929. automatically. Needs more memory than Simple Refresh, but redraws the display 
  930. much faster.
  931.  
  932. If you have a SuperBitMap Window, you have allocated the display memory 
  933. yourself, and your window will therefore not be destroyed by other windows.
  934.  
  935. If you change the size of a Simple Refresh Window, or it is revealed after 
  936. having been overlapped, Intuition will tell you that you need to refresh the 
  937. window. A Smart Refresh Window will only ask you to redraw its display if you 
  938. enlarged it.
  939.  
  940. The IDCMP message "REFRESHWINDOW" tells you that the window needs to be 
  941. refreshed. (See chapter 8 IDCMP for more about IDCMP flags.)
  942.  
  943. IMPORTANT! If your program receive a REFRESHWINDOW message you must call the 
  944. functions BeginRefresh() - EndRefresh():
  945.  
  946. - BeginRefresh() will make the redrawing as fast as possible. Only the 
  947. destroyed pieces of the window will be refreshed.
  948.  
  949. - EndRefresh() tells Intuition that you are finished with the redrawing.
  950.  
  951. If you receive a REFRESHWINDOW message and you do not want to redraw the 
  952. display, you should still call the two functions. This will clear up the system 
  953. and reorganize the Layer Library.
  954.  
  955. 2.5  INITIALIZE A WINDOW
  956.  
  957. Before you can open a window you need to initialize a NewWindow structure which 
  958. looks like this:
  959.  
  960. struct NewWindow
  961. {
  962.   SHORT LeftEdge, TopEdge;
  963.   SHORT Width, Height;
  964.   UBYTE DetailPen, BlockPen;
  965.   ULONG IDCMPFlags;
  966.   ULONG Flags;
  967.   struct Gadget *FirstGadget;
  968.   struct Image *CheckMark;
  969.   UBYTE *Title;
  970.   struct Screen *Screen;
  971.   struct BitMap *BitMap;
  972.   SHORT MinWidth, MinHeight;
  973.   SHORT MaxWidth, MaxHeight;
  974.   USHORT Type;
  975. };
  976.  
  977. LeftEdge:
  978.     
  979. Initial x position of the window.
  980.  
  981. TopEdge:
  982.     
  983. Initial y position of the window.
  984.  
  985. Width:
  986.     
  987. Initial width of the window. If the window is connected to a high-resolution 
  988. screen, it can be anything between 1 and 640. Otherwise (low-resolution screen) 
  989. it can be between 1 and 320.
  990.  
  991. Height:
  992.     
  993. Initial height of the window. Can be anything between 1 and the height of the 
  994. screen.
  995.  
  996. DetailPen:
  997.     
  998. The colour register used to draw the text with.
  999.  
  1000. BlockPen:
  1001.     
  1002. The colour register used for block fills etc.
  1003.  
  1004. IDCMPFlags:
  1005.     
  1006. See chapter 8 IDCMP for a list and explanations of the flags.
  1007.               
  1008. Flags:
  1009.     
  1010. If you want any System Gadgets, a special window (Borderless, Backdrop etc), 
  1011. you set the desired flags:
  1012.  
  1013.     
  1014. System Gadgets:
  1015.  
  1016.     
  1017. WINDOWCLOSE This will put the Close Gadget into the top left corner of your 
  1018. window. (Remember that this is the only System Gadget your program need to 
  1019. response to. Intuition will simply inform you that the user wants to close the 
  1020. window, but you need to close the window yourself by calling the CloseWindow() 
  1021. function.
  1022.  
  1023.     
  1024. WINDOWDRAG This makes the whole title bar into a gadget, which allows the user 
  1025. to move around the Window.
  1026.  
  1027.     
  1028. WINDOWDEPTH If you want that the user should be able to push the window in 
  1029. front, or behind all other windows you set this flag. The gadgets (to the back 
  1030. and to the front) will be placed in the top right corner of the window.
  1031.  
  1032.     
  1033. WINDOWSIZING This enables the user to resize the window as desired. (You can 
  1034. specify the maximum and minimum size of the window by setting the 
  1035. MinWidth/MinHeight/MaxWidth/MaxHeight variables)
  1036.                 
  1037.     
  1038. The Size Gadget will be placed in the right border as default (SIZEBRIGHT), but 
  1039. can also be put in the bottom border (set the flag SIZEBOTTOM) if you want the 
  1040. window display to be as wide as possible.
  1041.  
  1042.     
  1043. Special Windows:
  1044.               
  1045.     
  1046. BACKDROP Set this flag if you want a Backdrop Window.
  1047.  
  1048.     
  1049. BORDERLESS Set this flag if you want a Borderless Window.
  1050.     
  1051. GIMMEZEROZERO Set this flag if you want a Gimmezerozero Window.
  1052.  
  1053.     
  1054. SUPER_BITMAP Set this flag if you want a SuperBitMap Window. (If you are going 
  1055. to use your own allocated BitMap you also need to set the BitMap variable to 
  1056. point to your BitMap structure. Explained later in this chapter.)
  1057.  
  1058.     
  1059. Refreshing Flags. If you do not use a SuperBitMap Window you need to set one of 
  1060. these two flags:
  1061.  
  1062.     
  1063. SIMPLE_REFRESH Your program must redraw the display itself.
  1064.  
  1065.     
  1066. SMART_REFRESH Intuition will automatically redraw the display if necessary. It 
  1067. is only when the user make the window bigger you need to redraw the display 
  1068. yourself.
  1069.  
  1070.     
  1071. Other flags:
  1072.  
  1073.     
  1074. REPORTMOUSE Set this flag if you want to receive the pointer movements as x,y 
  1075. coordinates. (See chapter 8 IDCMP for more information.)
  1076.  
  1077.     
  1078. NOCAREREFRESH Set this flag if you do not want to receive any messages telling 
  1079. you to redraw your window.
  1080.  
  1081.     
  1082. RMBTRAP Set this flag if you do not want that the user to be able to access any 
  1083. menus while this window is active. (If you want that the right mouse button on 
  1084. the mouse should be used for something else than menu operations, you should 
  1085. set this flag. See chapter 8 IDCMP for more information.)
  1086.  
  1087.     
  1088. ACTIVATE Set this flag if you want the window to become  active when it is 
  1089. opened. The user can of course activate some other window later if he/she 
  1090. wants. (Clicking inside a window will activate it, and all input will go to the 
  1091. new active window. All other windows will become inactive, and their title bars 
  1092. will become "ghosted".)
  1093.  
  1094. FirstGadget:
  1095.     
  1096. A pointer to the first Gadget in your list, or NULL if you do not have any own 
  1097. gadgets connected to the window. (See chapter 4 GADGETS for more information 
  1098. about gadgets.)
  1099.  
  1100. CheckMark:
  1101.     
  1102. A pointer to an Image structure (See chapter 3 GRAPHICS for more information 
  1103. about Image structures) which will be used for selected menus items. (See 
  1104. chapter 7 MENUS for more information about menus.) If no pointer is given 
  1105. (NULL) Intuition will use the default checkmark.
  1106.  
  1107. Title:
  1108.     
  1109. A pointer to a NULL-terminated string that will be used as window's title. The 
  1110. string will appear on the title bar, at the top of the window.
  1111.  
  1112. Screen:
  1113.     
  1114. A pointer to your Custom Screen, or NULL if the window should be connected to 
  1115. the Workbench Screen. (If the window is connected to the Workbench Screen set 
  1116. the Type variable to WBENCHSCREEN, otherwise set it to CUSTOMSCREEN.)
  1117.  
  1118. BitMap:
  1119.     
  1120. If you are going to use a SuperBitMap Window, then you need to give Intuition a 
  1121. pointer to your own initialized BitMap structure, otherwise write NULL. 
  1122. (Remember to set the Flag SUPER_BITMAP, and you should probably also make the 
  1123. window into a Gimmezerozero Window.)
  1124.     
  1125. If you have asked for the System Gadget WINDOWSIZING you need to decide the 
  1126. minimum/maximum size of your window, otherwise you can ignore these variables. 
  1127. If any variable is set to zero the initial size (Width/Height) will be used as 
  1128. max/min size:
  1129.  
  1130. MinWidth:
  1131.     
  1132. Minimum width of the window.
  1133.  
  1134. MinHeight:
  1135.     
  1136. Minimum height of the window.
  1137.  
  1138. MaxWidth:
  1139.     
  1140. Maximum width of the window.
  1141.  
  1142. MaxHeight:
  1143.     
  1144. Maximum height of the window.
  1145.  
  1146. Type:
  1147.     
  1148. If your window should be connected to the Workbench Screen you write 
  1149. WBENCHSCREEN, otherwise you write CUSTOMSCREEN. (If you set the CUSTOMSCREEN 
  1150. flag you need to give the Screen variable a pointer to your already opened 
  1151. Custom Screen.
  1152.               
  1153.     
  1154. It is common that you declare and initialize the NewWindow structure with your 
  1155. requirements, except that you ignore (NULL) the Screen pointer. You then open 
  1156. your Custom Screen, and first now initialize the Screen pointer with the 
  1157. pointer returned from the OpenScreen() function. (See Example 2 for more 
  1158. information.)
  1159.  
  1160. 2.6  OPEN A WINDOW
  1161.  
  1162. The procedure to open windows is very similar to open Custom Screens. The idea 
  1163. is that you declare a NewWindow structure (similar to NewScreen) and initialize 
  1164. it with the requirements You then simply call the function OpenWindow() 
  1165. (similar to OpenScreen()) with your NewWindow structure, and the function 
  1166. returns a pointer to your Window structure. You will now not need the NewWindow 
  1167. structure any more (if you do not want to open more windows using the same 
  1168. structure of course).
  1169.  
  1170. This is how you call the OpenWindow() function:
  1171.  
  1172. my_window = OpenWindow( &my_new_window );
  1173.  
  1174. my_window has been declared as:
  1175. struct Window *my_window;
  1176.   
  1177. my_new_window has been declared as:
  1178. struct NewWindow my_new_window;
  1179. and has been initialized with your requirements.
  1180.  
  1181. OpenWindow() will return a pointer to your Window structure. If it could not 
  1182. open the Window (for example, not enough memory) it will return NULL. Remember 
  1183. therefore to check what OpenWindow() returned:
  1184.  
  1185. if( my_window == NULL )
  1186. {
  1187.   /* PANIC! Could not open the window */
  1188. }
  1189.  
  1190. 2.7  WINDOW STRUCTURE
  1191.  
  1192. Once you have opened the window you will receive a pointer (my_window) to a 
  1193. Window structure:
  1194. struct Window
  1195. {
  1196.     struct Window *NextWindow;  /* Pointer to next window. */
  1197.     SHORT LeftEdge, TopEdge;    /* Position of the window. */
  1198.     SHORT Width, Height;        /* Size of the window. */
  1199.     SHORT MouseY, MouseX;       /* Position of the pointer */
  1200.                                 /* relative to the top left */
  1201.                                 /* corner of the window. */
  1202.     SHORT MinWidth, MinHeight;  /* Minimum/Maximum size of */
  1203.     USHORT MaxWidth, MaxHeight; /* the window. */
  1204.  
  1205.     ULONG Flags;                /* The window's flags. */
  1206.  
  1207.     struct Menu *MenuStrip;     /* Pointer to the window's */
  1208.                                 /* first menu. */
  1209.  
  1210.     UBYTE *Title;               /* The window's title. */
  1211.  
  1212.     struct Requester *FirstRequest;
  1213.     struct Requester *DMRequest;
  1214.     SHORT ReqCount;
  1215.  
  1216.     struct Screen *WScreen;     /* A pointer to the Screen */
  1217.                                 /* which the window is */
  1218.                                 /* connected to. */
  1219.     struct RastPort *RPort;     /* The window's RastPort. */
  1220.  
  1221.     BYTE BorderLeft, BorderTop, BorderRight, BorderBottom;
  1222.  
  1223.     struct RastPort *BorderRPort; /* If your window is a */
  1224.                                   /* Gimmezerozero this a */
  1225.                                   /* pointer the the Outer */
  1226.                                   /* window's RastPort. */
  1227.  
  1228.     struct Gadget *FirstGadget;
  1229.     struct Window *Parent, *Descendant;
  1230.  
  1231.     USHORT *Pointer;            /* Data for the Pointer. */
  1232.     BYTE PtrHeight;             /* Height of the pointer. */
  1233.     BYTE PtrWidth;              /* Width of the pointer. */
  1234.     BYTE XOffset, YOffset;      /* "Hot Spot" of the pointer. */
  1235.  
  1236.     ULONG IDCMPFlags;           /* The IDCMP flags. */
  1237.  
  1238.     struct MsgPort *UserPort, *WindowPort;
  1239.     struct IntuiMessage *MessageKey;
  1240.  
  1241.     UBYTE DetailPen, BlockPen;
  1242.     struct Image *CheckMark;
  1243.  
  1244.     UBYTE *ScreenTitle;         /* The title of the screen */
  1245.                                 /* which the window is */
  1246.                                 /* connected to. */
  1247.  
  1248.     /* These are only used if you have opened a */
  1249.     /* Gimmezerozero window: */
  1250.     SHORT GZZMouseX; /* Position of the mouse relative to */
  1251.     SHORT GZZMouseY; /* the inner window. */
  1252.     SHORT GZZWidth;  /* Size of the inner window. */
  1253.     SHORT GZZHeight;
  1254.  
  1255.     UBYTE *ExtData;
  1256.     BYTE *UserData;
  1257.     struct Layer *WLayer;
  1258.     struct TextFont *IFont;
  1259. };
  1260.  
  1261. 2.8  OPEN A SUPERBITMAP WINDOW
  1262.  
  1263. The difference in opening a normal window and a SuperBitMap window is that 
  1264. Intuition will allocate display memory for the normal window automatically, 
  1265. while a SuperBitMap window has to allocate the memory itself. However, it is 
  1266. actually not so hard as it may seem. You just need to follow these steps:
  1267.  
  1268. 1. Declare and initialize a NewWindow structure with your    requirements.
  1269.    (Set the Flags = SUPER_BITMAP, and BitMap=NULL)
  1270.  
  1271. struct NewWindow my_new_window={ .... };
  1272.  
  1273. 2. Declare a BitMap structure:
  1274.  
  1275. struct BitMap my_bitmap;
  1276.  
  1277. 3. Initialize your own BitMap by calling the function:
  1278.  
  1279. InitBitMap( &my_bitmap, Depth, Width, Height );
  1280.  
  1281. &my_bitmap:
  1282.     
  1283. A pointer to the my_bitmap structure.
  1284. Depth:
  1285.     
  1286. Number of bitplanes to use.
  1287. Width:
  1288.     
  1289. The width of the BitMap.
  1290. Height:
  1291.     
  1292. The height of the BitMap.
  1293.  
  1294. 4. Allocate display memory for the BitMap:
  1295.  
  1296. for( loop=0; loop < Depth; loop++)
  1297.   if( (my_bitmap.Planes[loop] = AllocRaster( Width,
  1298.     Height )) == NULL )
  1299.   {
  1300.     /* PANIC! Not enough memory */
  1301.   }
  1302.  
  1303. 5. After you have allocated the display memory, it normally best to clear the 
  1304. Bitplanes:
  1305.  
  1306. for( loop=0; loop < Depth; loop++)
  1307.   BltClear(my_bitmap.Planes[loop], RASSIZE(Width, Height), 0);
  1308.  
  1309.  
  1310. 6. Make sure the NewWindow's BitMap pointer is pointing to your BitMap 
  1311. structure:
  1312.  
  1313. my_new_window.BitMap=&my_bitmap;
  1314.  
  1315. 7. At last you can open the window:
  1316.  
  1317. my_window = OpenWindow( &my_new_window );
  1318.  
  1319. 8. Do not forget to close the window, AND deallocate the    display memory:
  1320.  
  1321. CloseWindow( my_window );
  1322.  
  1323. for( loop=0; loop < Depth; loop++)
  1324.  if( my_bitmap.Planes[loop] )
  1325.    FreeRaster( my_bitmap.Planes[loop], Width, Height );
  1326.  
  1327. 2.9  MAKE YOUR OWN CUSTOM POINTER
  1328.  
  1329. Each window can have its individual pointer. When the window becomes active the 
  1330. pointer can change image. This makes it easier for the user to see which window 
  1331. is active, and can also give the user a hint about what the computer is doing. 
  1332. For example, a wordprocessor can have a pointer that looks similar to a pencil, 
  1333. and when the computer is busy, the pointer change to a little Zzz symbol.
  1334.  
  1335. If your window is going to use a "custom" pointer you need to:
  1336.  
  1337. 1. Allocate and initialize a Sprite data structure.
  1338. 2. Use the function SetPointer() to change the window's pointer.
  1339.  
  1340. When you are going to make a new image for your pointer, you first need to 
  1341. sketch how it should look like. The pointer is actually a Sprite (See chapter 
  1342. 10 SPRITES for more information about Sprites), and can therefore be up to 16 
  1343. pixels wide, and be as tall as you want. You may use 3 colours, and 
  1344. transparent. (Since the pointer is a Sprite (no. 0) it can move between 
  1345. different screens with different resolutions, without destroying the display.)
  1346.  
  1347. A nice "arrow" pointer (16 pixels wide, 16 lines high) may look something like 
  1348. this:
  1349.  
  1350. 0000000200000000      0: Transparent
  1351. 0000002200000000      1: Red
  1352. 0000023200000000      2: Black
  1353. 0000231200000000      3: White
  1354. 0002311200000000
  1355. 0023111222222200
  1356. 0231111133333320
  1357. 2311111111111132
  1358. 0211111111111112
  1359. 0021111222221112
  1360. 0002111200023112
  1361. 0000211200023112
  1362. 0000021200023112
  1363. 0000002200023112
  1364. 0000000200023112
  1365. 0000000000022222
  1366.  
  1367. You now need to translate this into Sprite Data. Each line of the pointer will 
  1368. be translated into two words of data. The first word represents the first 
  1369. Bitplane, and the second word the second Bitplane. The idea is that if you want 
  1370. colour 0 both Bitplane zero and one should be 0, if you want colour 1 Bitplane 
  1371. zero should be 1 and Bitplane one 0 and so on:
  1372.  
  1373. Colour  Bitplane One   Bitplane Zero           Since
  1374. ------------------------------------------------------------
  1375.   0           0              0         Binary 00 = Decimal 0
  1376.   1           0              1            "   01 =    "    1
  1377.   2           1              0            "   10 =    "    2
  1378.   3           1              1            "   11 =    "    3
  1379.  
  1380. The data for the pointer would then look like this:
  1381.  
  1382.    Bitplane ZERO          Bitplane ONE
  1383.  
  1384. 0000 0000 0000 0000    0000 0001 0000 0000
  1385. 0000 0000 0000 0000    0000 0011 0000 0000
  1386. 0000 0010 0000 0000    0000 0111 0000 0000
  1387. 0000 0110 0000 0000    0000 1101 0000 0000
  1388. 0000 1110 0000 0000    0001 1001 0000 0000
  1389. 0001 1110 0000 0000    0011 0001 1111 1100
  1390. 0011 1111 1111 1100    0111 0000 1111 1110
  1391. 0111 1111 1111 1110    1100 0000 0000 0011
  1392. 0011 1111 1111 1110    0100 0000 0000 0001
  1393. 0001 1110 0000 1110    0010 0001 1111 0001
  1394. 0000 1110 0000 1110    0001 0001 0001 1001
  1395. 0000 0110 0000 1110    0000 1001 0001 1001
  1396. 0000 0010 0000 1110    0000 0101 0001 1001
  1397. 0000 0000 0000 1110    0000 0011 0001 1001
  1398. 0000 0000 0000 1110    0000 0001 0001 1001
  1399. 0000 0000 0000 0000    0000 0000 0001 1111
  1400.  
  1401. The last step is to translate the binary numbers to base hexadecimal. Group the 
  1402. binary number in four and translate it to Hexadecimal:
  1403.  
  1404. 0000 =  0
  1405. 0001 =  1
  1406. 0010 =  2
  1407. 0011 =  3
  1408. 0100 =  4
  1409. 0101 =  5
  1410. 0110 =  6
  1411. 0111 =  7
  1412. 1000 =  8
  1413. 1001 =  9
  1414. 1010 =  A
  1415. 1011 =  B
  1416. 1100 =  C
  1417. 1101 =  D
  1418. 1110 =  E
  1419. 1111 =  F
  1420.  
  1421.  
  1422. The result will look like this:
  1423.  
  1424. ZERO:    ONE:
  1425. ------------
  1426. 0000    0100
  1427. 0000    0300
  1428. 0200    0700
  1429. 0600    0d00
  1430. 0E00    1900
  1431. 1E00    31FC
  1432. 3FFC    60FE
  1433. 7FFE    c003
  1434. 3FFE    4001
  1435. 1E0E    21F1
  1436. 0E0E    1119
  1437. 060E    0919
  1438. 020E    0519
  1439. 000E    0319
  1440. 000E    0119
  1441. 0000    001F
  1442.  
  1443. Since the Amiga need to store the position of the pointer, the size etc, you 
  1444. should also declare two empty words at the top, and two empty words at the 
  1445. bottom of the Sprite data. These words will be initialized and maintained by 
  1446. Intuition, so you do not need to bother about them.
  1447.  
  1448. A declaration and initialization of a nice arrow as Sprite data for a pointer 
  1449. would therefore be: (A hexadecimal number as 3FFE will written in C be 0x3FFE.)
  1450.  
  1451. UWORD chip my_sprite_data[36]=
  1452. {
  1453.  0x0000, 0x0000, /* Used by Intuition only. */
  1454.  
  1455.  0x0000, 0x0100,
  1456.  0x0000, 0x0300,
  1457.  0x0200, 0x0700,
  1458.  0x0600, 0x0D00,
  1459.  0x0E00, 0x1900,
  1460.  0x1E00, 0x31FC,
  1461.  0x3FFC, 0x60FE,
  1462.  0x7FFE, 0xC003,
  1463.  0x3FFE, 0x4001,
  1464.  0x1E0E, 0x21F1,
  1465.  0x0E0E, 0x1119,
  1466.  0x060E, 0x0919,
  1467.  0x020E, 0x0519,
  1468.  0x000E, 0x0319,
  1469.  0x000E, 0x0119,
  1470.  0x0000, 0x001F,
  1471.  
  1472.  0x0000, 0x0000  /* Used by Intuition only. */
  1473. };
  1474.  
  1475. It is actually not so complicated once you get used to it, but to make the life 
  1476. a bit easier I have written some utilities which will help you with translating 
  1477. graphics to sprite data. See the TOOL drawer for more information.
  1478.  
  1479. The last step is to call the function SetPointer() which would look like this:
  1480.  
  1481. SetPointer( my_window, my_sprite_data, 16, 16, 0, -7);
  1482.  
  1483. my_window:
  1484.     
  1485. Pointer to the window.
  1486. my_sprite_data:
  1487.     
  1488. Pointer to the Sprite Data.
  1489. 16:
  1490.     
  1491. Height.
  1492. 16:
  1493.     
  1494. Width. (Must be 16 or less!)
  1495. 0:
  1496.     
  1497. XOffset, left side. (Position of the Hot Spot)
  1498. -7:
  1499.     
  1500. YOffset, 7 lines down.
  1501.     
  1502. -"-
  1503.  
  1504. The "Hot Spot" is the pixel which should be the sensitive spot on the pointer. 
  1505. On the default pointer it is on the top left side, but on our custom pointer it 
  1506. should be on the left side (0), half way down (-7).
  1507.  
  1508. To restore the default pointer you simply call the function ClearPointer():
  1509.  
  1510. ClearPointer( my_window );
  1511.  
  1512. Since you are going to use graphics data it is important that the data is 
  1513. placed in the Chip Memory. Chip Memory is the first 512 KB of RAM, and the 
  1514. graphics routines in the Amiga demands that Sprite Data, as well as other 
  1515. graphics data, is placed there. (The reason why is that the CPU on the Amiga 
  1516. can reach the first 9MB of RAM, while the Blitter (a graphics co-processor) 
  1517. only can reach the first 512 KB.
  1518.  
  1519. There will soon be a new Chip set for the Amiga 500 and 2000 which enables the 
  1520. Blitter etc to reach the first 1 MB, but up to now the data MUST be placed 
  1521. somewhere in the memory between $00000 to 7FFFF.)
  1522.  
  1523. If you are using Lattice C Compiler V5.0 or higher it is very simple. You only 
  1524. need to place the little word "chip" in front of the data. Eg:
  1525.  
  1526. UWORD chip graphics_data[]={ ... };
  1527.  
  1528. On the Lattice C Compiler V4.0 you can compile the source with the added 
  1529. command: "-acdb" which will load everything into the Chip Memory. Eg:
  1530.  
  1531. lc -acdb -Lm my_program.c
  1532.  
  1533. This will do both the lc1 and lc2 compilation, and it will also link the code 
  1534. together with the standard math library. Everything is loaded into Chip Memory.
  1535.  
  1536. If you do not have one of these C compilers you will probably find out how to 
  1537. do it in your manual. REMEMBER! If you do not tell the compiler to always put 
  1538. the graphics in the Chip Memory you can end up with horrible bugs. It may 
  1539. sometimes work, especially if you have an unexpanded Amiga, but it will 
  1540. probably crash on an expanded Amiga.
  1541.  
  1542.  
  1543. 2.10  FUNCTIONS
  1544.  
  1545. Here are some functions that are often used together with windows:
  1546.  
  1547. OpenWindow()
  1548.  
  1549. This function will open a window with the characteristics defined in the 
  1550. NewWindow structure. It returns a pointer to a Window structure.
  1551.  
  1552. If you are going to use the Workbench screen, and it has been closed, it will 
  1553. automatically reopen. If you on the other hand is going to connect the window 
  1554. to a Custom screen, you need to open it yourself before calling the 
  1555. OpenWindow() function.
  1556.   
  1557. Synopsis:
  1558.     
  1559. my_window = OpenWindow( my_new_window );
  1560.  
  1561. my_window:
  1562.     
  1563. struct Window *) Pointer to a Window structure or NULL if the window could not 
  1564. be opened.
  1565.  
  1566. my_new_window:
  1567.     
  1568. (
  1569. struct NewWindow *) Pointer to a NewWindow structure which has been initialized 
  1570. with your requirements.
  1571.  
  1572. CloseWindow()
  1573.  
  1574. This function will close a window you have previously opened. Remember that you 
  1575. need to close all windows connected to a screen before you may close the 
  1576. screen, and all opened windows must have been closed before your program quits.
  1577.  
  1578. Synopsis:
  1579.     
  1580. CloseWindow( my_window );
  1581.  
  1582. my_window:
  1583.     
  1584. (struct Window *) Pointer to a Window structure which has previously been 
  1585. initialized by an OpenWindow() call.
  1586.  
  1587. MoveWindow()
  1588.  
  1589. This function will move a window. It has the same effect as if the user would 
  1590. have moved the window by using the Drag Gadget.
  1591.  
  1592. Synopsis:
  1593.     
  1594. MoveWindow( my_window, delta_x, delta_y );
  1595.  
  1596. my_window:
  1597.     
  1598. (struct Window *) Pointer to a Window structure which has previously been 
  1599. initialized by an OpenWindow() call.
  1600.  
  1601. delta_x:
  1602.     
  1603. (long) Deltamovement horizontally.
  1604.  
  1605. delta_y:
  1606.     
  1607. (long) Deltamovement vertically.
  1608.  
  1609. SizeWindow()
  1610.  
  1611. This function will change the size of the window as desired. It has the same 
  1612. effect as if the user would have resized the window by using the Size Gadget.
  1613.  
  1614.  
  1615. Synopsis:
  1616.     
  1617. SizeWindow( my_window, delta_x, delta_y );
  1618.  
  1619. my_window:
  1620.     
  1621. (struct Window *) Pointer to a Window structure which has previously been 
  1622. initialized by an OpenWindow() call.
  1623.  
  1624. delta_x:
  1625.     
  1626. (long) Number of pixels the horizontally size of the window will change.
  1627.  
  1628. delta_y:
  1629.     
  1630. (long) Number of pixels the vertically size of the window will change.
  1631.  
  1632. WindowToFront()
  1633.  
  1634. This function will put the window in front of all other windows.
  1635.  
  1636. Synopsis:
  1637.     
  1638. WindowToFront( my_window );
  1639.  
  1640. my_window:
  1641.     
  1642. (struct Window *) Pointer to a Window structure which has previously been 
  1643. initialized by an OpenWindow() call.
  1644.  
  1645. WindowToBack()
  1646.  
  1647. This function will push the window behind all other windows.
  1648.  
  1649. Synopsis:
  1650.     
  1651. WindowToBack( my_window );
  1652.  
  1653. my_window:
  1654.     
  1655. (struct Window *) Pointer to a Window structure which has previously been 
  1656. initialized by an OpenWindow() call.
  1657.  
  1658. SetWindowTitles()
  1659.  
  1660. This function allows you to change the window title after the window has been 
  1661. opened.
  1662.   
  1663. Synopsis:  SetWindowTitles( my_window, window_t, screen_t );
  1664.   
  1665. my_window:
  1666.     
  1667. (struct Window *) Pointer to a Window structure which has previously been 
  1668. initialized by an OpenWindow() call.
  1669.  
  1670. window_t:
  1671.     
  1672. (char *) Pointer to a NULL-terminated string which will become the window's 
  1673. title, or
  1674.     
  1675.  0 : clear title bar, or
  1676.     
  1677. -1 : keep the old title.
  1678.  
  1679. screen_t:
  1680.     
  1681. (char *) Pointer to a NULL-terminated string which will become the window's 
  1682. screen title, or
  1683.     
  1684. 0 : clear title bar, or
  1685.     
  1686. -1 : keep the old title.
  1687.  
  1688. WindowLimits()
  1689.  
  1690. This function will change the maximum/minimum size limits of the window. Any 
  1691. values which are set to 0 will remain unchanged.
  1692.  
  1693. Synopsis:
  1694.     
  1695. WindowLimits( my_window, min_w, min_h, max_w, max_h );
  1696.  
  1697. my_window:
  1698.     
  1699. (struct Window *) Pointer to a Window structure which has previously been 
  1700. initialized by an OpenWindow() call.
  1701. min_w:
  1702.     
  1703. (long) Minimum width of the window.
  1704.  
  1705. min_h:
  1706.     
  1707. (long) Minimum height of the window.
  1708.  
  1709. max_w:
  1710.     
  1711. (long) Maximum width of the window.
  1712.  
  1713. max_h:
  1714.     
  1715. (long) Maximum height of the window.
  1716.  
  1717. SetPointer()
  1718.  
  1719. This function allows you to change the window's pointer.
  1720.   
  1721. Synopsis:
  1722.     
  1723. SetPointer( my_window, data, height, width, x, y );
  1724.  
  1725. my_window:
  1726.     
  1727. (struct Window *) Pointer to a Window structure which has previously been 
  1728. initialized by an OpenWindow() call.
  1729.  
  1730. data:
  1731.     
  1732. (short *) Pointer to the Sprite data.
  1733.  
  1734. width:
  1735.     
  1736. (long) The width of the pointer. Less or equal to 16.
  1737.  
  1738. height:
  1739.     
  1740. (long) The height of the pointer. Can be any height.
  1741.  
  1742. x:
  1743.     
  1744. (long) The pointer's "Hot Spot" x position.
  1745.  
  1746. y:
  1747.     
  1748. (long) The pointer's "Hot Spot" y position.
  1749.  
  1750. ClearPointer()
  1751.  
  1752. This will remove the "custom" pointer, and replace it with Intuition's default 
  1753. pointer.
  1754.   
  1755. Synopsis:
  1756.     
  1757. ClearPointer( my_window );
  1758.  
  1759. my_window:
  1760.     
  1761. (struct Window *) Pointer to a Window structure which has previously been 
  1762. initialized by an OpenWindow() call.
  1763.  
  1764. ReportMouse()
  1765.  
  1766. You can call this function if you want the window to start/ stop reporting the 
  1767. mouse position. (See chapter 8 IDCMP for more information about REPORTMOUSE.)
  1768.   
  1769. Synopsis:
  1770.     
  1771. ReportMouse( my_window, boolean );
  1772.  
  1773. my_window:
  1774.     
  1775. (struct Window *) Pointer to a Window structure which has previously been 
  1776. initialized by an OpenWindow() call.
  1777.  
  1778. boolean:
  1779.     
  1780. (long) Set to TRUE if you want the window to start reporting mouse position, 
  1781. else set to FALSE, and the window will stop reporting.
  1782.  
  1783. BeginRefresh()
  1784.  
  1785. This function will speed up your redrawing of the window. You  should call this 
  1786. function before you start to refresh the window, and only the parts that needs 
  1787. to be redrawn are redrawn.
  1788.  
  1789. Synopsis:
  1790.     
  1791. BeginRefresh( my_window );
  1792.  
  1793. my_window:
  1794.     
  1795. (struct Window *) Pointer to a Window structure which has previously been 
  1796. initialized by an OpenWindow() call.
  1797.  
  1798. EndRefresh()
  1799.  
  1800. This function will tell Intuition that you have finished with your redrawings. 
  1801. IMPORTANT! If you receive a REFRESHWINDOW  message, you must call the functions 
  1802. BeginRefresh() and EndRefresh(), even if you do not want to redraw anything.
  1803.   
  1804. Synopsis:
  1805.     
  1806. EndRefresh( my_window );
  1807.  
  1808. my_window:
  1809.     
  1810. (struct Window *) Pointer to a Window structure which has previously been 
  1811. initialized by an OpenWindow() call.
  1812.  
  1813. 2.11  EXAMPLES
  1814.  
  1815. We have now looked at different types of windows, how to connect System 
  1816. Gadgets, the steps to customize your pointer and much more. It is now again 
  1817. time to look at some examples:
  1818.  
  1819. Example 1
  1820. This program will open a normal window which is connected to the Workbench 
  1821. Screen. It will display it for 30 seconds, and then close it.
  1822.  
  1823. Example 2
  1824. This program will open a high resolution 16 colour Custom Screen and a normal 
  1825. window which is connected to it. It will display it for 30 seconds, and then 
  1826. close the Custom Screen and the window.
  1827.  
  1828. Example 3
  1829. This program will open a normal window which is connected to the Workbench 
  1830. Screen. The window will use all System Gadgets, and will automatically Activate 
  1831. the window. It will display it for 30 seconds, and then close it. (Remember 
  1832. that the Close Gadget does NOT close the window by itself, it will only inform 
  1833. you that the user wants to close it. But in this example we will not listen to 
  1834. what the user wants.)
  1835.  
  1836. Example 4
  1837. This program will open two normal windows which are connected to the Workbench 
  1838. Screen. The windows will use all System Gadgets. It will display them for 30 
  1839. seconds, and then close them.
  1840.  
  1841. Example 5
  1842. This program will open a Borderless window which is connected to the Workbench 
  1843. Screen. It will display it for 30 seconds, and then quit.
  1844.  
  1845. Example 6
  1846. Same as Example 5 except that the window will also use all System Gadgets.
  1847.  
  1848. Example 7
  1849. This program will open three windows, two are normal and the third is a 
  1850. Backdrop window. The windows will use all System Gadgets, except the Backdrop 
  1851. window, which only can use the close-window gadget. After 30 seconds the 
  1852. program quits. (Try to push either window 1 or 2 behind the Backdrop window.)
  1853.  
  1854. Example 8
  1855. This program will open a SuperBitMap window which is connected to the Workbench 
  1856. Screen. Since it is a SuperBitMap we also make the window into a Gimmezerozero 
  1857. window. The window will use all System Gadgets, and some boxes will be drawn. 
  1858. It will display the window for 30 seconds, and then close it. (Shrink the 
  1859. window, and then enlarge it again, and you will noticed that the lines are 
  1860. still there!)
  1861.  
  1862. Example 9
  1863. This program will open a normal window with all system gadgets connected to it. 
  1864. If you activate the window, the pointer will change shape into a "nice" arrow.
  1865.  
  1866. Example 10
  1867. This program will open a two normal windows with all system gadgets connected 
  1868. to them. If the first window is Activated, the pointer will change shapes into 
  1869. a Zzz symbol, if the second window is activated, the pointer will look like a 
  1870. pistol.
  1871.  
  1872.  
  1873. GRAPHICS
  1874.  
  1875. 3.1  INTRODUCTION
  1876.  
  1877. We have now looked at how to open different types of screens, and how to open 
  1878. different types of windows connected to the screens etc. It is all very good, 
  1879. but what would Intuition be without any graphics to display in the 
  1880. screens/windows?
  1881.  
  1882. Intuition's main idea is to make the communication between the program and the 
  1883. user as easy as possible. Graphics enables you to display the results that the 
  1884. computer has calculated in an understandable way (a picture says more than...). 
  1885. Graphics makes it also much easier to use the program, and can warn the user if 
  1886. something dangerous is going to happen: It is very easy to press the wrong 
  1887. button if you have got a question like "OK to erase disk?", but if there also 
  1888. had been a picture showing a cross with the text "RIP" on, you would probably 
  1889. have been a bit more careful.
  1890.  
  1891. There exist both a low- and a high-level way of making graphics. The low-level 
  1892. approach (Graphics Primitives) is not described in this chapter since it is not 
  1893. related to Intuition. The low-level graphics routines are very fast, but if you 
  1894. are not careful they can trash menus etc. We will here concentrate our self on 
  1895. the high-level approach which is supported by Intuition, and is a safe way of 
  1896. drawing.
  1897.  
  1898. 3.2  LINES TEXT PICTURES
  1899.  
  1900. Intuition gives you three different methods of making graphics:
  1901. - You can draw lines (Borders).
  1902. - Print text (IntuiText).
  1903. - Or you can directly print graphics images (Images).
  1904.  
  1905. 3.3  BORDERS
  1906.  
  1907. Border has a bit misleading name since you are not limited to only draw 
  1908. borders, you may draw any kind of shapes which is made out of connecting lines. 
  1909. A Border structure may also be connected to other Border structures, so 
  1910. everything which can be drawn with lines, can be drawn with Intuition's Border
  1911. structure. 
  1912.  
  1913. 3.3.1  THE BORDER STRUCTURE
  1914.  
  1915. When you want to draw lines you need to declare and initialize a Border 
  1916. structure which look like this:
  1917.  
  1918. struct Border
  1919. {
  1920.   SHORT LeftEdge, TopEdge;
  1921.   SHORT FrontPen, BackPen, DrawMode;
  1922.   SHORT Count;
  1923.   SHORT *XY;
  1924.   struct Border *NextBorder;
  1925. };
  1926.  
  1927. LeftEdge, TopEdge:
  1928.     
  1929. Start position of the lines.
  1930.  
  1931. FrontPen:
  1932.     
  1933. Colour register used to draw the lines.
  1934.  
  1935. BackPen:
  1936.     
  1937. This variable is for the moment unused.
  1938.  
  1939. DrawMode:
  1940.     
  1941. Must be either JAM1 or XOR. If the JAM1 flag is set, the colour specified 
  1942. (FrontPen) will be used to draw the lines regardless what the background colour 
  1943. is. The XOR flag makes the lines to be drawn with the binary complement of the 
  1944. background colours.
  1945.  
  1946. Count:
  1947.     
  1948. The number of coordinates there is in the XY array. (See below for more 
  1949. information.)
  1950.  
  1951. XY:
  1952.     
  1953. A pointer to an array of coordinates used to draw the lines. (See below for 
  1954. more information.)
  1955.  
  1956. NextBorder:
  1957.     
  1958. A pointer to the next Border structure if there exist one, else NULL.
  1959.  
  1960. 3.3.2  COORDINATES
  1961.  
  1962. If you want to draw this:
  1963.  
  1964. (10,10)        (25,10)
  1965.    *--------------*
  1966.                   |      (35,12)
  1967.                   |         *
  1968.                   |         |
  1969.                   *---------*
  1970.                (25,14)   (35,14)
  1971.  
  1972. The array of coordinates would look like this:
  1973.  
  1974. SHORT my_points[]=
  1975. {
  1976.   10,10, /* Start at position (10,10) */
  1977.   25,10, /* Draw a line to the right to position (25,10) */
  1978.   25,14, /* Draw a line down to position (25,14) */
  1979.   35,14, /* Draw a line to the right to position (35,14) */
  1980.   35,12  /* Finish of by drawing a line up to position (35,12) */ 
  1981. };
  1982.  
  1983. The array contains 5 pair of coordinates, so the variable Count should be set 
  1984. accordingly. The entire Border structure would therefore look something like 
  1985. this:
  1986.  
  1987. struct Border my_border=
  1988. {
  1989.   0, 0,        /* LeftEdge, TopEdge. */
  1990.   3,           /* FrontPen, colour register 3. */
  1991.   0,           /* BackPen, for the moment unused. */
  1992.   JAM1,        /* DrawMode, draw the lines with colour 3. */
  1993.   5,           /* Count, 5 pair of coordinates in the array. */
  1994.   my_points,   /* XY, pointer to the array with the */
  1995.                /* coordinates. */
  1996.                /* (Remember my_points == &my_points[0]) */
  1997.   NULL         /* NextBorder, no other Border structures */
  1998.                /* comes after this one. */
  1999. };
  2000. 3.4  HOW TO USE THE BORDER STRUCTURE
  2001.  
  2002. The Border structure is either used to draw lines in a screen or window, but 
  2003. can also be used to draw lines connected to a Gadget, Requester or Menu. (See 
  2004. chapter 4, 5 and 7 for more information about Gadgets, Requesters and Menus.)
  2005.  
  2006. If you want to connect a Border structure with a Gadget etc, you simply 
  2007. initialize the Gadget structure with a pointer to the Border structure, and 
  2008. Intuition will draw the lines for you. This will be explained later.
  2009.  
  2010. If you want to draw the lines in a screen or window you need to tell Intuition 
  2011. that you want it to use the structure to make some lines. You do it by calling 
  2012. the function DrawBorder():
  2013.  
  2014. Synopsis
  2015. :  DrawBorder( rast_port, border, x, y );
  2016.  
  2017. rast_port:
  2018.     
  2019. (struct RastPort *) Pointer to a RastPort.
  2020.  
  2021.     
  2022. If the lines should be drawn in a window, and my_window is a pointer to that 
  2023. window, you write:
  2024.     
  2025. my_window->RPort.
  2026.           
  2027.     
  2028. If the lines should be drawn in a Screen, and my_screen is a pointer to that 
  2029. screen, you write:
  2030.            
  2031.     
  2032. my_screen->RastPort.
  2033.  
  2034. border:
  2035.     
  2036. (struct Border *) Pointer to a Border structure which has been initialized with 
  2037. your requirements.
  2038.  
  2039. x:
  2040.     
  2041. (long) Number of pixels added to the x coordinates.
  2042.  
  2043. y:
  2044.     
  2045. (long) Number of lines added to the y coordinates.
  2046.  
  2047.  
  2048. A call to draw some lines using my_border structure would look something like 
  2049. this:
  2050.   
  2051. DrawBorder( my_window->RPort, &my_border, 0, 0 );
  2052.  
  2053. If you have created a Border structure which, for example, draws a box, you can 
  2054. draw several boxes at different places just by changing the LeftEdge, RightEdge 
  2055. fields of the Border structure, or by changing the x, y fields in the function 
  2056. call. This shows how versatile Intuition's high-level way of drawing is.
  2057.  
  2058. 3.4  TEXT
  2059.  
  2060. Printing text in the Display is supported by the IntuiText structure. It is 
  2061. quite similar to the Border structure, and is executed in the same way. The 
  2062. only difference is that you need to tell Intuition what Font you want to use, 
  2063. and what text to print.
  2064.  
  2065. 3.4.1  THE INTUITEXT STRUCTURE
  2066.  
  2067. When you want to print text you need to declare and initialize a IntuiText 
  2068. structure which look like this:
  2069.  
  2070.  
  2071. struct IntuiText
  2072. {
  2073.   UBYTE FrontPen, BackPen;
  2074.   UBYTE DrawMode;
  2075.   SHORT LeftEdge;
  2076.   SHORT TopEdge;
  2077.   struct TextAttr *ITextFont;
  2078.   UBYTE *IText;
  2079.   struct IntuiText *NextText;
  2080. };
  2081.  
  2082. FrontPen:
  2083.     
  2084. Colour register used to draw the text with.
  2085.  
  2086. BackPen:
  2087.     
  2088. Colour register used to draw the background of the text.
  2089.  
  2090. DrawMode:
  2091.     
  2092. There exist three different way of printing the text:
  2093.  
  2094.     
  2095. JAM1  The colour specified (FrontPen) will be used to draw the text with, the 
  2096. background is unchanged.
  2097.  
  2098.     
  2099. JAM2  The FrontPen colour will be used to draw the text with, the background is 
  2100. drawn with the BackPen colour.
  2101.  
  2102.     
  2103. XOR   The text is drawn with the the binary complement of the background.
  2104.  
  2105. LeftEdge, TopEdge:
  2106.     
  2107. Start position of the text.
  2108.  
  2109. ITextFont:
  2110.     
  2111. A pointer to a TextAttr structure which tells Intuition what font, size and 
  2112. style etc to print the text with. Set to NULL if you want to use the default 
  2113. font. (See below for more information.)
  2114.  
  2115. IText:
  2116.     
  2117. A pointer to a NULL-terminated string that should be printed.
  2118.  
  2119. NextText:
  2120.     
  2121. A pointer to the next IntuiText structure if there exist one, else write NULL.
  2122.  
  2123. 3.4.2  FONTS
  2124.  
  2125. You can tell Intuition to print the text with a specific font/style. You only 
  2126. need to declare and initialize a TextAttr structure, and give your IntuiText 
  2127. structure a pointer to the TextAttr structure.
  2128.  
  2129. The TextAttr structure look like this:
  2130.  
  2131. struct TextAttr
  2132. {
  2133.   STRPTR ta_Name;
  2134.   UWORD ta_YSize;
  2135.   UBYTE ta_Style
  2136.   UBYTE ta_Flags;
  2137. };
  2138.  
  2139.  
  2140. We will for the moment only discuss how to access the ROM-fonts (the fonts 
  2141. which are always available in ROM), and will wait with Disk-fonts (fonts which 
  2142. your program can access from the disk).
  2143. There exist only one ROM-font for the moment, and that one is called Topaz. It 
  2144. exist in two sizes, 64/32 and 80/40 (high/low-resolution) characters per line, 
  2145. and can be printed in five different styles, normal, bold, italic, underlined 
  2146. and extended,which can be combined as desired.
  2147.  
  2148. ta_Name:
  2149.     
  2150. Name of the font. Set it to "topaz.font" for the moment.
  2151.  
  2152. ta_YSize:
  2153.     
  2154. Font height. Can either be TOPAZ_SIXTY (64/32) or TOPAZ_EIGHTY (80/40).
  2155.  
  2156. ta_Style:
  2157.     
  2158. Style (normal, bold, underlined, italic and extended). Set the desired flags:
  2159.  
  2160.     
  2161. FS_NORMAL
  2162.     
  2163. No special style.
  2164.     
  2165. FSF_EXTENDED
  2166.     
  2167. Extended font, wider than normal.
  2168.     
  2169. FSF_ITALIC
  2170.     
  2171. Italic, slanted 1:2 to the right.
  2172.     
  2173. FSF_BOLD
  2174.     
  2175. Bold, thicker than normal.
  2176.     
  2177. FSF_UNDERLINED
  2178.     
  2179. Underlined, line under the baseline.
  2180.  
  2181. ta_Flags:
  2182.     
  2183. Preferences. Should for the moment be set to FPF_ROMFONT.
  2184.  
  2185.  
  2186. Here is an example on how you can print some text with underlined, italic 
  2187. characters:
  2188.  
  2189. struct TextAttr my_font=
  2190. {
  2191.   "topaz.font",                 /* Topaz font. */
  2192.   TOPAZ_EIGHTY,                 /* 80/40 characters. */
  2193.   FSF_ITALIC | FSF_UNDERLINED,  /* Underlined italic chars. */ 
  2194.   FPF_ROMFONT                   /* Exist in ROM. */
  2195. };
  2196.  
  2197. UBYTE my_text[]="This is the text that will be printed!";
  2198.  
  2199. struct IntuiText my_intui_text=
  2200. {
  2201.   2,         /* FrontPen, colour register 2. */
  2202.   3,         /* BackPen, colour register 3. */
  2203.   JAM2,      /* DrawMode, draw the characters with colour 2, */
  2204.              /* on a colour 3 background. */ 
  2205.   0, 0,      /* LeftEdge, TopEdge. */
  2206.   &my_font,  /* ITextFont, use my_font. */
  2207.   my_text,   /* IText, the text that will be printed. */
  2208.              /* (Remember my_text = &my_text[0].) */
  2209.   NULL       /* NextText, no other IntuiText structures are */
  2210.              /* connected. */
  2211. };
  2212.  
  2213. 3.4.3  HOW TO USE THE INTUITEXT STRUCTURE
  2214.  
  2215. The IntuiText structure is either used to print text in a screen or window, but 
  2216. can also be used to print text connected to a Gadget, Menu or Requester. Same 
  2217. as with drawing lines with the Border structure.
  2218.  
  2219. When you want to print text in a window/screen you simply call the function 
  2220. PrintIText():
  2221. Synopsis
  2222. :   PrintIText( rast_port, intui_text, x, y );
  2223.  
  2224. rast_port:
  2225.     
  2226. (struct RastPort *) Pointer to a RastPort.
  2227.  
  2228.     
  2229. If the text should be printed in a window, and my_window is a pointer to that 
  2230. window, you write:
  2231.     
  2232. my_window->RPort.
  2233.           
  2234.     
  2235. If the text should be printed in a Screen, and my_screen is a pointer to that 
  2236. screen, you write:
  2237.     
  2238. my_screen->RastPort.
  2239.  
  2240. intui_text:
  2241.     
  2242. (struct IntuiText *) Pointer to a IntuiText structure which has been 
  2243. initialized with your requirements.
  2244.  
  2245. x:
  2246.     
  2247. (long) Number of pixels added to the x position of the characters.
  2248.  
  2249. y:
  2250.     
  2251. (long) Number of lines added to the y position of the characters.
  2252.  
  2253.  
  2254. A call to print some text using my_intui_text structure would look something 
  2255. like this:
  2256.   
  2257. PrintIText( my_window->RPort, &my_intui_text, 0, 0 );
  2258.  
  2259. 3.5  IMAGES
  2260.  
  2261. We have now looked at how to draw lines and print text. We will finish off by 
  2262. looking at how to print a whole image directly. The procedure can be divided 
  2263. into three steps:
  2264.  
  2265. 1. Declare and initialize the data which should be drawn.
  2266. 2. Declare and initialize an Image structure.
  2267. 3. Call the function DrawImage() to draw the image.
  2268.  
  2269. 3.5.1  IMAGE DATA
  2270.  
  2271. Intuition wants to have the image data structured into blocks of 16-bit memory 
  2272. words (UWORD), organized into rectangular areas (BitPlanes). You may have up to 
  2273. 6 BitPlanes (4 if you are displaying the image on a high-resolution screen). 
  2274. The colour of each pixel is determined by the binary number of the BitPlanes. 
  2275. For example, to get a pixel with colour 6 on a screen with a Depth of 4, 
  2276. BitPlane zero and three should be 0, and BitPlane one and two should be 1, 
  2277. since the binary number 0110 is equal to the decimal number 6.
  2278.  
  2279. A little arrow can for example look like this: (1 BitPlane = 2 colours)
  2280.  
  2281. Image      16-Bit memory words    Hexadecimal representation
  2282. ------------------------------------------------------------
  2283.  
  2284. 0001000    0001 0000 0000 0000    1 0 0 0
  2285. 0011100    0011 1000 0000 0000    3 8 0 0
  2286. 0111110    0111 1100 0000 0000    7 C 0 0
  2287. 1111111    1111 1110 0000 0000    F E 0 0
  2288. 0001000    0001 0000 0000 0000    1 0 0 0
  2289. 0001000    0001 0000 0000 0000    1 0 0 0
  2290. 0001000    0001 0000 0000 0000    1 0 0 0
  2291. 0001000    0001 0000 0000 0000    1 0 0 0
  2292.  
  2293. Even if the Image only is 7 pixels wide, we needed to make the Image data 16 
  2294. (bits) pixels wide, since Intuition wants the data ordered into 16-bit memory 
  2295. words. (Of course, when we print it out we can tell Intuition that the image 
  2296. should be only 7 pixels wide.)
  2297.  
  2298. Each group of four pixels is then translated into a hexadecimal value. See 
  2299. table:
  2300.  
  2301. Binary => Hexadecimal
  2302. ---------------------
  2303. 0000 =    0
  2304. 0001 =    1
  2305. 0010 =    2
  2306. 0011 =    3
  2307. 0100 =    4
  2308. 0101 =    5
  2309. 0110 =    6
  2310. 0111 =    7
  2311. 1000 =    8
  2312. 1001 =    9
  2313. 1010 =    A
  2314. 1011 =    B
  2315. 1100 =    C
  2316. 1101 =    D
  2317. 1110 =    E
  2318. 1111 =    F
  2319.  
  2320. A declaration and initialization of the data for the arrow image will therefore 
  2321. look like this:
  2322.  
  2323. UWORD chip my_image_data[]=
  2324. {
  2325.   0x1000, /* BitPlane ZERO */
  2326.   0x3800,
  2327.   0x7C00,
  2328.   0xFE00,
  2329.   0x1000,
  2330.   0x1000,
  2331.   0x1000,
  2332.   0x1000
  2333. };
  2334.  
  2335. Since the image data is made out of one BitPlane, the arrow will be drawn in 
  2336. colour 1, and the background in colour 0. 
  2337.  
  2338. If the image is wider than 16 pixels you need more than one word per line. Here 
  2339. is an image which is 20 pixels wide, and will therefore require two words per 
  2340. line:
  2341.  
  2342. Image                  16-Bit memory words (2 words)
  2343. ---------------------------------------------------------------
  2344.  
  2345. 11111111111111111111   1111 1111 1111 1111  1111 0000 0000 0000
  2346. 00111110000001111100   0011 1110 0000 0111  1100 0000 0000 0000
  2347. 00001111100111110000   0000 1111 1001 1111  0000 0000 0000 0000
  2348. 00111110000001111100   0011 1110 0000 0111  1100 0000 0000 0000
  2349. 11111111111111111111   1111 1111 1111 1111  1111 0000 0000 0000
  2350.  
  2351.  
  2352. We translate the binary numbers into hexadecimal, and we end up with:
  2353.  
  2354. UWORD chip my_image_data[]=
  2355. {
  2356.   0xFFFF, 0xF000, /* BitPlane ZERO */
  2357.   0x3E07, 0xC000,
  2358.   0x0F9F, 0x0000,
  2359.   0x3E07, 0xC000,
  2360.   0xFFFF, 0xF000
  2361. };
  2362.  
  2363. If we want more than two colours we need more than one BitPlane. A four-colour 
  2364. face can look something like this:
  2365.  
  2366. 003333300000     0: Blue (Normal Workbench colours)
  2367. 033333330000     1: White
  2368. 332232233000     2: Black
  2369. 323333323000     3: Orange
  2370. 331131133000
  2371. 331131133000
  2372. 331232133000
  2373. 331232133000
  2374. 333333333000
  2375. 332333233000
  2376. 033222330000
  2377. 033333330000
  2378. 003333300000
  2379.  
  2380. We translate it into 16-Bit memory words organized into two Bitplanes (Two 
  2381. BitPlanes = 4 colours):
  2382.  
  2383. Colour   Bitplane ONE   Bitplane ZERO   SINCE
  2384. ------------------------------------------------------
  2385. 0        0              0               00 (b) = 0 (d)
  2386. 1        0              1               01 (b) = 1 (d)
  2387. 2        1              0               10 (b) = 2 (d)
  2388. 3        1              1               11 (b) = 3 (d)
  2389.  
  2390.  
  2391. Bitplane ONE          Bitplane ZERO
  2392. -----------------------------------------
  2393.  
  2394. 0011 1110 0000 0000   0011 1110 0000 0000
  2395. 0111 1111 0000 0000   0111 1111 0000 0000
  2396. 1111 1111 1000 0000   1100 1001 1000 0000
  2397. 1111 1111 1000 0000   1011 1110 1000 0000
  2398. 1100 1001 1000 0000   1111 1111 1000 0000
  2399. 1100 1001 1000 0000   1111 1111 1000 0000
  2400. 1101 1101 1000 0000   1110 1011 1000 0000
  2401. 1101 1101 1000 0000   1110 1011 1000 0000
  2402. 1111 1111 1000 0000   1111 1111 1000 0000
  2403. 1111 1111 1000 0000   1101 1101 1000 0000
  2404. 0111 1111 0000 0000   0110 0011 0000 0000
  2405. 0111 1111 0000 0000   0111 1111 0000 0000
  2406. 0011 1110 0000 0000   0011 1110 0000 0000
  2407.  
  2408. Each group of four pixels is then translated into a hexadecimal value:
  2409.  
  2410. Bitplane ONE          Bitplane ZERO
  2411. -----------------------------------
  2412.  
  2413. 3 E 0 0               3 E 0 0
  2414. 7 F 0 0               7 F 0 0
  2415. F F 8 0               C 9 8 0
  2416. F F 8 0               B E 8 0
  2417. C 9 8 0               F F 8 0
  2418. C 9 8 0               F F 8 0
  2419. D D 8 0               E B 8 0
  2420. D D 8 0               E B 8 0
  2421. F F 8 0               F F 8 0
  2422. F F 8 0               D D 8 0
  2423. 7 F 0 0               6 3 0 0
  2424. 7 F 0 0               7 F 0 0
  2425. 3 E 0 0               3 E 0 0
  2426.  
  2427. A declaration and initialization of the data for the face image will therefore 
  2428. look like this:
  2429.  
  2430. USHORT chip my_image_data[]=
  2431. {
  2432.   0x3E00, /* Bitplane ZERO */
  2433.   0x7F00,
  2434.   0xC980,
  2435.   0xBE80,
  2436.   0xFF80,
  2437.   0xFF80,
  2438.   0xEB80,
  2439.   0xEB80,
  2440.   0xFF80,
  2441.   0xDD80,
  2442.   0x6300,
  2443.   0x7F00,
  2444.   0x3E00,
  2445.  
  2446.   0x3E00, /* Bitplane ONE */
  2447.   0x7F00,
  2448.   0xFF80,
  2449.   0xFF80,
  2450.   0xC980,
  2451.   0xC980,
  2452.   0xDD80,
  2453.   0xDD80,
  2454.   0xFF80,
  2455.   0xFF80,
  2456.   0x7F00,
  2457.   0x7F00,
  2458.   0x3E00
  2459. };
  2460.  
  2461. Remember that all Image Data MUST be in Chip Memory!
  2462.  
  2463. 3.5.2  THE IMAGE STRUCTURE
  2464.  
  2465. The Image structure look like this:
  2466.  
  2467. struct Image
  2468. {
  2469.   SHORT LeftEdge, TopEdge;
  2470.   SHORT Width, Height, Depth;
  2471.   SHORT *ImageData;
  2472.   UBYTE PlanePick, PlaneOnOff;
  2473.   struct Image *NextImage;
  2474. };
  2475.  
  2476. LeftEdge:
  2477.     
  2478. X position of the Image.
  2479.  
  2480. TopEdge:
  2481.     
  2482. Y position of the Image.
  2483.  
  2484. Width:
  2485.     
  2486. The actual width of the Image.
  2487.  
  2488. Height:
  2489.     
  2490. The height of the Image.
  2491.  
  2492. Depth:
  2493.     
  2494. Number of Bitplanes used for the Image.
  2495.  
  2496. ImageData:
  2497.     
  2498. A pointer to the Image data.
  2499.  
  2500. PlanePick:
  2501.     
  2502. Which Bitplanes of the displaying element should be changed/affected by the 
  2503. Image. (See below for more information.)
  2504.  
  2505. PlaneOnOff:
  2506.     
  2507. What should happen to the Bitplanes of the displaying element that were not 
  2508. affected. Should they be filled with 1's or 0's. (See below for more 
  2509. information.)
  2510.  
  2511. NextImage:
  2512.     
  2513. A pointer to the next Image structure if there exist one, else NULL.
  2514.  
  2515. 3.5.3  PLANEPICK
  2516.  
  2517. The advantages with the PlanePick/PlaneOnOff fields are that you can print the 
  2518. Image into a display of any depth, print the same Image in different colours, 
  2519. and it will eliminate unnecessary memory-waste when using coloured Images.
  2520.  
  2521. PlanePick tells Intuition which Bitplanes of the display to be affected by the 
  2522. Image. For every "picked" plane, the next successive Bitplane of the image is 
  2523. printed there. For example:
  2524.  
  2525. If we set PlanePick to 1, Bitplane zero would be affected. If we then printed 
  2526. the arrow Image, we would get the arrow drawn with colour 1, and the background 
  2527. drawn with colour 0.
  2528.  
  2529. If we had instead set PlanePick to 2, Bitplane one would have been affected, 
  2530. which would result in that the arrow would have been drawn with colour 2, and 
  2531. the background still drawn with colour 0.
  2532.  
  2533. If our Image would consist of several Bitplanes, the lowest picked plane would 
  2534. be affected by the lowest Bitplane, and so on. If we take our face Image for 
  2535. example, and we want to draw it with colour 3, 2 1 and 0, we want to affect 
  2536. Bitplane zero and BitPlane one of the display. We would therefore need to set 
  2537. PlanePick to 3, see table:
  2538.  
  2539. Bitplane to affect   PlanePick
  2540. ------------------------------
  2541.  
  2542. No planes affected   0000 = 0
  2543. Plane 0              0001 = 1
  2544. Plane 1              0010 = 2
  2545. Plane 1 and 0        0011 = 3
  2546. Plane 2              0100 = 4
  2547. Plane 2 and 0        0101 = 5
  2548. Plane 2 and 1        0110 = 6
  2549. Plane 2, 1 and 0     0111 = 7
  2550. Plane 3              1000 = 8
  2551. Plane 3 and 0        1001 = 9
  2552. Plane 3 and 1        1010 = A
  2553. and so on...
  2554.  
  2555. If we want to draw it with colour 5, 4, 1 and 0, we want to affect Bitplane two 
  2556. and zero:
  2557.  
  2558. (000=colour 0, 001=colour 1, 100=colour 4, 101=colour 5)
  2559.  ^ ^           ^ ^           ^ ^           ^ ^
  2560.  210           210           210           210 (BitPlanes)
  2561.  
  2562. We would then set PlanePick to 5 (0101).
  2563.  
  2564. 3.5.4  PLANEONOFF
  2565.  
  2566. PlaneOnOff decides what should happen to the Bitplanes of the displaying 
  2567. element that were not affected by PlanePick. Should these Bitplanes be filled 
  2568. with 1's or 0's.
  2569.  
  2570. For example, if we want to print the little arrow in colour 5 and the 
  2571. background in colour 1 the pixels should have the values 0001 (colour 1) and 
  2572. 0101 (colour 5). We want the Image to affect Bitplane two, so PlanePick is set 
  2573. to 4 (0100). But we also want Bitplane zero to be filled with 1's, so 
  2574. PlaneOnOff is set to 1 (0001).
  2575.  
  2576. With help of PlanePick and PlaneOnOff you can even print filled rectangles 
  2577. without any Image data. You only need to set Width and Height as desired, and 
  2578. then set Depth to 0 (no Bitplanes), PlanePick to 0000 (no Bitplanes should be 
  2579. used) and PlaneOnOff to the colour you want.
  2580.  
  2581. 3.5.5  HOW TO USE THE IMAGE STRUCTURE
  2582.  
  2583. The Image structure is either used to print images in a screen or window, but 
  2584. can also be used to print images connected to a Gadget, Menu or Requester. Same 
  2585. as Intuition's other Graphics structures.
  2586.  
  2587. When you want to print an image in a window/screen you simply call the function 
  2588. DrawImage():
  2589.  
  2590. Synopsis
  2591. :  DrawImage( rast_port, image, x, y );
  2592.  
  2593.  
  2594. rast_port:
  2595.     
  2596. (struct RastPort *) Pointer to a RastPort.
  2597.  
  2598.     
  2599. If the images should be drawn in a window, and my_window is a pointer to that 
  2600. window, you write:
  2601.     
  2602. my_window->RPort.
  2603.  
  2604.     
  2605. If the images should be drawn in a Screen, and my_screen is a pointer to that 
  2606. screen, you write:
  2607.     
  2608. my_screen->RastPort.
  2609.  
  2610. image:
  2611.     
  2612. (struct Image *) Pointer to an Image structure which has been initialized with 
  2613. your requirements.
  2614.  
  2615. x:
  2616.     
  2617. (long) Number of pixels added to the x position of the image.
  2618.  
  2619. y:
  2620.     
  2621. (long) Number of lines added to the y position of the image.
  2622.  
  2623.  
  2624. A call to print an image using my_image structure would look something like 
  2625. this:
  2626.  
  2627. DrawImage( my_window->RPort, &my_image, 0, 0 );
  2628.  
  2629. 3.6  FUNCTIONS
  2630.  
  2631. Here are the three functions you use when you want to draw 
  2632. lines/characters/images into a RastPort (Screen/Window):
  2633.  
  2634. DrawBorder()
  2635.  
  2636. This function draws the specified Borders into a RastPort (Screen/Window).
  2637.  
  2638. Synopsis:  DrawBorder( rast_port, border, x, y );
  2639.  
  2640. rast_port:
  2641.     
  2642. (struct RastPort *) Pointer to a RastPort.
  2643.  
  2644.     
  2645. If the lines should be drawn in a window, and my_window is a pointer to that 
  2646. window, you write:
  2647.     
  2648. my_window->RPort.
  2649.           
  2650.     
  2651. If the lines should be drawn in a Screen, and my_screen is a pointer to that 
  2652. screen, you write:
  2653.     
  2654. my_screen->RastPort.
  2655.  
  2656. border:
  2657.     
  2658. (struct Border *) Pointer to a Border structure which has been initialized with 
  2659. your requirements.
  2660.  
  2661. x:
  2662.     
  2663. (long) Number of pixels added to the x coordinates.
  2664.  
  2665. y:
  2666.     
  2667. (long) Number of lines added to the y coordinates.
  2668.  
  2669.  
  2670.  
  2671. PrintIText()
  2672.  
  2673. This function prints text into a RastPort (Screen/Window).
  2674.  
  2675. Synopsis:   PrintIText( rast_port, intui_text, x, y );
  2676.  
  2677. rast_port:
  2678.     
  2679. (struct RastPort *) Pointer to a RastPort.
  2680.  
  2681.     
  2682. If the text should be printed in a window, and my_window is a pointer to that 
  2683. window, you write:
  2684.     
  2685. my_window->RPort.
  2686.           
  2687.     
  2688. If the text should be printed in a Screen, and my_screen is a pointer to that 
  2689. screen, you write:
  2690.     
  2691. my_screen->RastPort.
  2692.  
  2693. intui_text:
  2694.     
  2695. (struct IntuiText *) Pointer to a IntuiText structure which has been 
  2696. initialized with your requirements.
  2697.  
  2698. x:
  2699.     
  2700. (long) Number of pixels added to the x position of the characters.
  2701.  
  2702. y:
  2703.     
  2704. (long) Number of lines added to the y position of the characters.
  2705.  
  2706.  
  2707. DrawImage()
  2708.  
  2709. This function draws the specified images into a RastPort (Screen/Window).
  2710.  
  2711. Synopsis:  DrawImage( rast_port, image, x, y );
  2712.  
  2713. rast_port:
  2714.     
  2715. (struct RastPort *) Pointer to a RastPort.
  2716.  
  2717.     
  2718. If the images should be drawn in a window, and my_window is a pointer to that 
  2719. window, you write:
  2720.     
  2721. my_window->RPort.
  2722.  
  2723.     
  2724. If the images should be drawn in a Screen, and my_screen is a pointer to that 
  2725. screen, you write:
  2726.     
  2727. my_screen->RastPort.
  2728.  
  2729. image:
  2730.     
  2731. (struct Image *) Pointer to an Image structure which has been initialized with 
  2732. your requirements.
  2733.  
  2734. x:
  2735.     
  2736. (long) Number of pixels added to the x position of the image.
  2737.  
  2738. y:
  2739.     
  2740. (long) Number of lines added to the y position of the image.
  2741.  
  2742. 3.7  EXAMPLES
  2743.  
  2744. Here are some examples on how to draw lines (Border), print text (IntuiText) 
  2745. and draw pictures (Image):
  2746.  
  2747. Example 1
  2748. This program will open a normal window which is connected to the Workbench 
  2749. Screen. We will then draw a strange line with help of Intuition's Border 
  2750. structure.
  2751.  
  2752. Example 2
  2753. This program will open a normal window which is connected to the Workbench 
  2754. Screen. We will then draw two rectangles with different colours. This shows how 
  2755. you can link Border structures to each other in order to get the desired 
  2756. effects.
  2757.  
  2758. Example 3
  2759. This program will open a normal window which is connected to the Workbench 
  2760. Screen. We will then print a text string with help of Intuition's IntuiText 
  2761. structure.
  2762.  
  2763. Example 4
  2764. Same as Example 3 except that the text will be printed with underlined italic 
  2765. characters.
  2766.  
  2767. Example 5
  2768. This program will open a normal window which is connected to the Workbench 
  2769. Screen. We will then draw the little nice arrow we talked so much about.
  2770.  
  2771. Example 6
  2772. Same as Example 5 except that we will draw it several times in different 
  2773. colours. This shows how PlanePick/PlaneOnOff works.
  2774.  
  2775. Example 7
  2776. This program will open a normal window which is connected to the Workbench 
  2777. Screen. We will then draw the nice 4 colour face that was described in chapter 
  2778. 3.5 IMAGES.
  2779.  
  2780. Example 8
  2781. This program will open a normal window which is connected to a 16-colour Custom 
  2782. screen. In the window we will draw the famous AMIGA-logo.
  2783.  
  2784.  
  2785. GADGETS
  2786.  
  2787. 4.1  INTRODUCTION
  2788.  
  2789. In this chapter we will look at how the user can communicate with the program. 
  2790. All programs which use Intuition should, if possible, be controlled by a mouse, 
  2791. since it is the most commonly used input device. Intuition's Gadgets will play 
  2792. a big role here.
  2793.  
  2794. A gadget can be a "button" which the user can click on, but it can also be a 
  2795. small knob which can be dragged (like a volume control on a radio). A gadget 
  2796. can even be a box where the user can enter a text string or a value. The 
  2797. advantages of using gadgets are almost uncountable. They are very well 
  2798. supported by Intuition which means that your program hardly needs to do 
  2799. anything, but still have an outstanding user interface which is both easy to 
  2800. understand as well as use.
  2801.  
  2802. 4.2  DIFFERENT TYPES OF GADGETS
  2803.  
  2804. There exist two types of gadgets: System gadgets, which we already have 
  2805. discussed in chapter 2.3 SYSTEM GADGETS, and Custom gadgets. For every window 
  2806. System gadgets always look the same, and are always placed in the same places. 
  2807. Custom Gadgets, however, can be placed wherever you want, and it is you who 
  2808. decide what they should look like.
  2809.  
  2810. 4.3  CUSTOM GADGETS
  2811.  
  2812. There exist four different types of Custom gadgets:
  2813. - Boolean gadget
  2814.     
  2815. On/Off (True/False) button.
  2816. - Proportional gadget
  2817.     
  2818. A small knob which can be moved around inside a container.
  2819. - String gadgets
  2820.     
  2821. Gadget which enables the user to enter a string.
  2822. - Integer gadget
  2823.     
  2824. Same as the String gadget, except that the user can only enter integer numbers.
  2825.  
  2826. 4.3.1  GRAPHICS FOR CUSTOM GADGETS
  2827.  
  2828. You can render the gadget with help of the high-level graphics utilities which 
  2829. are supported by Intuition (See chapter 3 GRAPHICS for more information). You 
  2830. can render the gadget with help of a Border structure, or an Image structure. 
  2831. You can even have a different rendering when the gadget is selected, 
  2832. highlighted.
  2833.  
  2834. It is of course possible to open gadgets with no rendering at all. The Drag 
  2835. gadget (System gadget) is a good example.
  2836.  
  2837. 4.3.2  POSITION
  2838.  
  2839. You can position the gadget anywhere on the display. The position is normally 
  2840. relative to the top left corner of the displaying element (Window, Requester 
  2841. etc). If you want you can position the gadget relative to some other sides than 
  2842. the top left corner:
  2843.  
  2844. If you want the gadget to be placed 10 pixels out and 20 lines down from the 
  2845. top left corner of a window, you set LeftEdge to 10, and TopEdge to 20. 
  2846. (LeftEdge etc are elements in the Gadget structure which is described later in 
  2847. the chapter.)
  2848.  
  2849. If you on the other hand want the gadget to always be 20 pixels above the 
  2850. bottom border of the window, and 10 pixels to the left of the right border, you 
  2851. set LeftEdge to -10 and TopEdge to -20 together with the Flags GRELRIGHT and 
  2852. GRELBOTTOM. (More about this later.)
  2853.  
  2854. 4.3.3  SIZE
  2855.  
  2856. You decide the width and height of the gadget (the select box of the gadget) by 
  2857. setting the Width and Height variables as desired.
  2858.  
  2859. If you set the Height to 25, the gadget will be 25 lines high.
  2860.  
  2861. If you on the other hand set the Height to -25 and you set the GRELHEIGHT flag, 
  2862. the gadget will always be 25 lines smaller than the containing element (window 
  2863. etc).
  2864.  
  2865. Same applies for the Width. If you set the Width to 50, the gadget will always 
  2866. be 50 pixels wide.
  2867.  
  2868. If you on the other hand set the Width to be -50 and you set the flag 
  2869. GRELWIDTH, the gadget will always be 50 pixels smaller than the containing 
  2870. element.
  2871.  
  2872. 4.4  INITIALIZE A CUSTOM GADGET
  2873.  
  2874. When you want to use a Custom gadget you need to declare and initialize a 
  2875. Gadget structure which look like this:
  2876.  
  2877. struct Gadget
  2878. {
  2879.   struct Gadget *NextGadget;
  2880.   SHORT LeftEdge, TopEdge, Width, Height;
  2881.   USHORT Flags;
  2882.   USHORT Activation;
  2883.   USHORT GadgetType;
  2884.   APTR GadgetRender;
  2885.   APTR SelectRender;
  2886.   struct IntuiText *GadgetText;
  2887.   LONG MutualExclude;
  2888.   APTR SpecialInfo;
  2889.   USHORT GadgetID;
  2890.   APTR UserData;
  2891. }
  2892.  
  2893. NextGadget:
  2894.     
  2895. A pointer to the next gadget in the list if there exist one, else NULL.
  2896.  
  2897. LeftEdge, TopEdge:
  2898.     
  2899. Position of the gadget's select box relative to the displaying element.
  2900.  
  2901. Width, Height:
  2902.     
  2903. Width and height of the gadget's select box.
  2904.  
  2905. Flags:
  2906.     
  2907. You must set one of the following four highlighting flags: (The gadget is 
  2908. highlighted when it is selected)
  2909.  
  2910.     
  2911. GADGHCOMP:  Complement the colours of all pixels in the gadget's select box.
  2912.  
  2913.     
  2914. GADGHBOX:   Draw a box around the the gadget's select box.
  2915.  
  2916.     
  2917. GADGHIMAGE: Display an alternative Image/Border.
  2918.     
  2919. GADGHNONE:  No highlighting.
  2920.  
  2921.     
  2922. If the gadget should be rendered as an Image set the flag GADGIMAGE, otherwise 
  2923. (render it with a Border structure, or no rendering at all) clear this flag.
  2924.  
  2925.     
  2926. If you want the position and/or size of the gadget to be relative to the size 
  2927. of the displaying element, set the desired flags:
  2928.  
  2929.     
  2930. GRELBOTTOM: TopEdge is used as an offset relative to the bottom of the 
  2931. displaying element, instead of an offset relative to the top of the displaying 
  2932. element.
  2933.  
  2934.     
  2935. GRELRIGHT:  LeftEdge is used as an offset relative to the right edge of the 
  2936. displaying element, instead of an offset relative to the left edge of the 
  2937. displaying element.
  2938.  
  2939.     
  2940. GRELWIDTH:  Width describes an increment to the width of the displaying 
  2941. element, instead of describing the absolute width of the gadget.
  2942.  
  2943.     
  2944. GRELRIGHT:  Height describes an increment to the height of the displaying 
  2945. element, instead of describing the absolute height of the gadget.
  2946.  
  2947.     
  2948. If this gadget is a toggle-select gadget (see Activation flags) you can set the 
  2949. SELECTED flag, and the gadget will be selected and highlighted when opened. If 
  2950. not, the gadget will be unselected and non-highlighted when opened.
  2951.                    
  2952.     
  2953. You can also examine this field to see if the SELECTED flag is set or not. If 
  2954. it is set, the gadget is selected, else it is unselected.
  2955.                    
  2956.     
  2957. If you want that the gadget should be disabled when opened, you set the flag 
  2958. GADDISABLED. Your program can later change this by calling the functions 
  2959. OnGadget() (enables the gadget) and OffGadget() (disables the gadget).
  2960.  
  2961. Activation:
  2962.     
  2963. Set the flags for the desired effects: (More about these later...)
  2964.                    
  2965.     
  2966. GADGIMMEDIATE: If you want your program to know immediately when the user 
  2967. selects this gadget, you should set this flag.
  2968.  
  2969.     
  2970. RELVERIFY:     If you want your program to receive a message when the user 
  2971. releases the gadget and the pointer is still inside the gadget's select box, 
  2972. you should set this flag.
  2973.  
  2974.     
  2975. FOLLOWMOUSE:   Set this flag if you want your program to receive mouse 
  2976. positions every time the user moves the mouse while this gadget is selected.
  2977.  
  2978.     
  2979. TOGGLESELECT:  Each time the user selects this gadget, the on/off state of the 
  2980. gadget (as well as the image) is toggled. Your program can later check the 
  2981. status of the gadget by examining the SELECTED bit in the Flags field.
  2982.  
  2983.     
  2984. BOOLEXTEND:    Set this flag if your gadget has a BoolInfo structure connected 
  2985. to it.
  2986.  
  2987.  
  2988.     
  2989. If your gadget is connected to a window you can set the following flags in 
  2990. order to change the size of the window's borders. (You can then put the gadget 
  2991. there.):
  2992.                    
  2993.     
  2994. RIGHTBORDER:   The width of the window's right border is calculated with help 
  2995. of the gadget's position and width.
  2996.  
  2997.     
  2998. LEFTBORDER:    The width of the window's left border is calculated with help of 
  2999. the gadget's position and width.
  3000.  
  3001.     
  3002. TOPBORDER:     The height of the window's top border is calculated with help of 
  3003. the gadget's position and height.
  3004.  
  3005.     
  3006. BOTTOMBORDER:  The height of the window's bottom border is calculated with help 
  3007. of the gadget's position and height.
  3008.  
  3009.  
  3010.     
  3011. If this gadget is connected to a requester you can set the ENDGADGET flag. The 
  3012. requester will only go away when a gadget with the ENDGADGET flag has been 
  3013. selected. (See chapter 5 REQUESTERS for more information about gadgets 
  3014. connected to requesters.)
  3015.  
  3016.     
  3017. Intuition will only care about these flags if the gadget is a String/Integer 
  3018. gadget:
  3019.                    
  3020.     
  3021. STRINGRIGHT:   Set this flag if you want the characters in the string to be 
  3022. right-justified.
  3023.  
  3024.     
  3025. STRINGCENTER:  Set this flag if you want the characters in the string to be 
  3026. center-justified. (The default is left-justified.)
  3027.  
  3028.     
  3029. LONGINT:       Set this flag if you want that the user should only be able to 
  3030. enter a 32-bit signed integer value.
  3031.  
  3032.     
  3033. ALTKEYMAP:     Set this flag if you want to use an alternative keymap. Remember 
  3034. to give the AltKeyMap pointer in the StringInfo structure a pointer to the 
  3035. keymap.
  3036.  
  3037. GadgetType:        You must set one of the following three flags:
  3038.  
  3039.     
  3040. BOOLGADGET:    Set this flag if you want a Boolean gadget.
  3041.  
  3042.     
  3043. STRGADGET:     Set this flag if you want a String/Integer gadget. If you want 
  3044. an Integer gadget you also need to set the Activation flag LONGINT. 
  3045.  
  3046.     
  3047. PROPGADGET:    Set this flag if you want a Proportional gadget.
  3048.  
  3049.     
  3050. The following two flags are only for gadgets connected to Gimmezerozero windows 
  3051. and requesters.
  3052.  
  3053.     
  3054. GZZGADGET:     If the gadget is connected to a Gimmezerozero window and you 
  3055. have set this flag, the gadget will be put in the outer window, and will not 
  3056. destroy any drawings etc in the inner window.
  3057.                                   
  3058.     
  3059. REQGADGET:     Set this flag if the gadget is connected to a requester.
  3060.  
  3061. GadgetRender:
  3062.     
  3063. A pointer to an Image or Border structure (See chapter 3 GRAPHICS for more 
  3064. information) which will be used to render the gadget. (If you supply a pointer 
  3065. to an Image structure you need to set the Flags variable to GADGIMAGE.) Set it 
  3066. to NULL if you do not want to supply the gadget with any graphics.
  3067.  
  3068. SelectRender:
  3069.     
  3070. A pointer to an alternative Image or Border structure which will be used when 
  3071. the gadget is highlighted. Remember to set the GADGHIMAGE bit in the Flags 
  3072. variable if you want to use an alternative Image/Border. (GadgetRender and 
  3073. SelectRender must point to the same type of data. If you have specified that 
  3074. you want to use an Image for the GadgetRender (GADGIMAGE), SelectRender must 
  3075. then also point to an Image structure.)
  3076.  
  3077. GadgetText:
  3078.     
  3079. A pointer to an IntuiText structure (See chapter 3 GRAPHICS for more 
  3080. information) which will be used to print some text in the gadget. Set it to 
  3081. NULL if you do not want any text connected to your gadget.
  3082.  
  3083. MutualExclude:
  3084.     
  3085. This field represent the first 32 gadgets in the list. If this gadget is 
  3086. selected, all specified gadgets in the MutualExclude field are deselected 
  3087. automatically. For example, if you want that gadget number 0, 2, 5 and 8 should 
  3088. be deselected (mutual excluded) when this gadget is selected, the MutualExclude 
  3089. field should be set to 293. ( 293(d) == 100100101(b) )
  3090.                    
  3091.     
  3092. Remember, the mutual exclude works only with toggle-select gadgets.
  3093.  
  3094. SpecialInfo:
  3095.     
  3096. If the gadget is a Proportional gadget you should here give Intuition a pointer 
  3097. to a PropInfo structure, or if the gadget is a String (Integer) gadget you 
  3098. should give Intuition a pointer to a StringInfo structure.
  3099.                    
  3100.     
  3101. If the gadget is a Boolean gadget you can connect a BoolInfo structure which 
  3102. will place a mask on the gadget's select box. (See below for more information.)
  3103.  
  3104. GadgetID
  3105.     
  3106. This variable is left for your own use. Intuition ignores this field.
  3107.  
  3108. UserData:
  3109.     
  3110. A pointer to any structure you may want to connect to the gadget. Intuition 
  3111. ignores this field.
  3112.  
  3113. 4.5  BOOLEAN GADGET
  3114.  
  3115. If you want a Boolean gadget you should declare and initialize the Gadget 
  3116. structure something like this:
  3117.  
  3118. struct my_gadget=
  3119. {
  3120.   NULL,          /* NextGadget, no more gadgets in the list. */
  3121.   40,            /* LeftEdge, 40 pixels out. */
  3122.   20,            /* TopEdge, 20 lines down. */
  3123.   60,            /* Width, 60 pixels wide. */
  3124.   20,            /* Height, 20 pixels lines high. */
  3125.   GADGHCOMP,     /* Flags, when this gadget is highlighted, */
  3126.                  /* the gadget will be rendered in the      */
  3127.                  /* complement colours:                     */
  3128.                  /* (Colour 0 (00) will become colour 3 (11) */
  3129.                  /* (Colour 1 (01)        - " -       2 (10) */
  3130.                  /* (Colour 2 (10)        - " -       1 (01) */
  3131.                  /* (Colour 3 (11)        - " -       0 (00) */  
  3132.   GADGIMMEDIATE| /* Activation, our program will receive a  */
  3133.   RELVERIFY,     /* message when the user has selected this */
  3134.                  /* gadget, and when the user has released  */
  3135.                  /* it.                                     */ 
  3136.   BOOLGADGET,    /* GadgetType, a Boolean gadget. */
  3137.   &my_border,    /* GadgetRender, a pointer to our Border */
  3138.                  /* structure.                            */
  3139.   NULL,          /* SelectRender, NULL since we do not    */
  3140.                  /* supply the gadget with an alternative */
  3141.                  /* image. (We complement the colours     */
  3142.                  /* instead.)                             */
  3143.   &my_text,      /* GadgetText, a pointer to our IntuiText */
  3144.                  /* structure.                             */
  3145.   NULL,          /* MutualExclude, no mutual exclude. */
  3146.   NULL,          /* SpecialInfo, no BoolInfo connected to it. */
  3147.   0,             /* GadgetID, no id. */
  3148.   NULL           /* UserData, no user data connected to the */
  3149.                  /* gadget. */
  3150. };
  3151.  
  3152. It is possible to connect a mask to a Boolean gadget. In that case the gadget 
  3153. would only be selected when the user clicks inside the selected (masked) area, 
  3154. and only that area would be highlighted. If you want to connect a mask to a 
  3155. Boolean gadget you need to declare and initialize a BoolInfo structure together 
  3156. with its mask.
  3157.  
  3158. The BoolInfo structure looks like this:
  3159.  
  3160. struct BoolInfo
  3161. {
  3162.   USHORT Flags;
  3163.   UWORD *Mask;
  3164.   ULONG Reserved;
  3165. };
  3166.  
  3167. Flags:
  3168.     
  3169. There exists only one flag for the moment: BOOLMASK.
  3170.  
  3171. Mask:
  3172.     
  3173. Pointer to the binary mask. (The width and height of the mask must be the same 
  3174. as the width and height of the select box.)
  3175.  
  3176. Reserved:
  3177.     
  3178. This field is reserved and should therefore be set to 0.
  3179.  
  3180. The binary mask is built up as an Image plane. Only the selected (1's) parts of 
  3181. the mask will be sensitive and highlighted.
  3182.  
  3183. A mask for a gadget with the width of 16 pixels, and the height of 8 pixels can 
  3184. look something like this: (Only the inner part of the select box will be 
  3185. sensitive and highlighted.)
  3186.  
  3187. Mask                16-Bit memory words    Hexadecimal
  3188. ------------------------------------------------------
  3189.  
  3190. 0000001111000000    0000 0011 1100 0000    03C0
  3191. 0000111111110000    0000 1111 1111 0000    0FF0
  3192. 0011111111111100    0011 1111 1111 1100    3FFC
  3193. 1111111111111111    1111 1111 1111 1111    FFFF
  3194. 1111111111111111    1111 1111 1111 1111    FFFF
  3195. 0011111111111100    0011 1111 1111 1100    3FFC
  3196. 0000111111110000    0000 1111 1111 0000    0FF0
  3197. 0000001111000000    0000 0011 1100 0000    03C0
  3198.  
  3199.  
  3200. The mask would in this case be declared/initialized like this:
  3201.  
  3202. UWORD my_mask[]=
  3203. {
  3204.   0x03C0,
  3205.   0x0FF0,
  3206.   0x3FFC,
  3207.   0xFFFF,
  3208.   0xFFFF,
  3209.   0x3FFC,
  3210.   0x0FF0,
  3211.   0x03C0
  3212. };
  3213.  
  3214. See Example6 for more information about the BoolInfo structure.
  3215.  
  3216. 4.6  STRING/INTEGER GADGET
  3217.  
  3218. String and Integer gadgets are a bit more complicated to declare since you need 
  3219. to supply the Gadget structure with a StringInfo structure. However, String and 
  3220. Integer gadgets allow the user to enter a string or an integer value without 
  3221. much effort from your side. Intuition takes care of most of the work, and you 
  3222. almost only need to decide how long and where the string gadget should be.
  3223.  
  3224. 4.6.1  STRINGINFO STRUCTURE
  3225.  
  3226. The StringInfo structure look like this:
  3227.  
  3228. struct StringInfo
  3229. {
  3230.   UBYTE *Buffer;
  3231.   UBYTE *UndoBuffer;
  3232.   SHORT BufferPosition;
  3233.   SHORT MaxChars;
  3234.   SHORT DispPos;
  3235.   SHORT UndoPos;
  3236.   SHORT NumChars;
  3237.   SHORT DispCount;
  3238.   SHORT CLeft, CTop;
  3239.   struct Layer *LayerPtr;
  3240.   LONG LongInt;
  3241.   struct KeyMap *AltKeyMap;
  3242. };
  3243.  
  3244. Buffer:
  3245.     
  3246. A pointer to a NULL-terminated string.
  3247.  
  3248. UndoBuffer:
  3249.     
  3250. A pointer to a NULL-terminated string which is used by Intuition to store an 
  3251. undo string. This must be at least as long as the Buffer string. When the user 
  3252. selects this gadget Intuition makes a copy of the Buffer string which will be 
  3253. copied back if the user presses AMIGA + Q. Since only one String/Integer gadget 
  3254. can be active at a time several String/Integer gadgets can use the same undo 
  3255. string.
  3256.  
  3257. MaxChars:
  3258.     
  3259. The maximum number of characters which may be entered. (Number of characters in 
  3260. the buffer + the NULL '\0' sign.)
  3261.  
  3262. BufferPos:
  3263.     
  3264. Cursor position in the buffer string.
  3265.  
  3266. DispPos:
  3267.     
  3268. Position of the first character which is displayed.
  3269.  
  3270. These variables are initialized and maintained by Intuition:
  3271.  
  3272. UndoPos:
  3273.     
  3274. Cursor position in the undo string.
  3275.  
  3276. NumChars:
  3277.     
  3278. Current number of characters in the buffer.
  3279.  
  3280. DispCount:
  3281.     
  3282. Current number of visible characters in the container.
  3283.  
  3284. CLeft, CTop:
  3285.     
  3286. Top left offset of the container.
  3287.  
  3288. LayerPtr:
  3289.     
  3290. Pointer to the Layer structures.
  3291.  
  3292. LongInt:
  3293.     
  3294. If this is an Integer gadget you can examine the value here to find out what 
  3295. the user has entered.
  3296.  
  3297. AltKeyMap:
  3298.     
  3299. A pointer to an alternative keymap. (Remember to set the flag ALTKEYMAP in the 
  3300. Activation field.)
  3301.  
  3302. 4.6.2  INITIALIZE A STRING/INTEGER GADGET
  3303.  
  3304. This is an example of how you can initialize a string gadget:
  3305.  
  3306. UBYTE my_buffer[50];
  3307. UBYTE my_undo_buffer[50];
  3308.  
  3309. struct StringInfo my_string_info=
  3310. {
  3311.   my_buffer,       /* Buffer, pointer to a NULL-terminated s. */
  3312.   my_undo_buffer,  /* UndoBuffer, pointer to a NULL-          */
  3313.                    /* terminated string. (Remember my_buffer  */
  3314.                    /* is equal to &my_buffer[0])              */
  3315.   0,               /* BufferPos, initial position of the */
  3316.                    /* cursor.                            */
  3317.   50,              /* MaxChars, 49 characters + NULL-sign. */
  3318.   0,               /* DispPos, first character in the string */
  3319.                    /* should be first character in the       */
  3320.                    /* display.                               */
  3321.  
  3322.   /* Intuition initializes and maintains these variables: */
  3323.  
  3324.   0,               /* UndoPos */
  3325.   0,               /* NumChars */
  3326.   0,               /* DispCount */
  3327.   0, 0,            /* CLeft, CTop */
  3328.   NULL,            /* LayerPtr */
  3329.   NULL,            /* LongInt */
  3330.   NULL,            /* AltKeyMap */
  3331. };
  3332.  
  3333. struct Gadget my_gadget=
  3334. {
  3335.   NULL,           /* NextGadget, no more gadgets in the list. */
  3336.   68,             /* LeftEdge, 68 pixels out. */
  3337.   30,             /* TopEdge, 30 lines down. */
  3338.   198,            /* Width, 198 pixels wide. */
  3339.   8,              /* Height, 8 pixels lines high. */
  3340.   GADGHCOMP,      /* Flags, draw the select box in the        */
  3341.                   /* complement colours. Note: it is actually */
  3342.                   /* only the cursor which will be drawn in   */
  3343.                   /* the complement colours (yellow). If you  */
  3344.                   /* set the flag GADGHNONE the cursor will   */
  3345.                   /* not be highlighted, and the user will    */
  3346.                   /* therefore not be able to see it.         */
  3347.   GADGIMMEDIATE|  /* Activation, our program will receive a  */
  3348.   RELVERIFY,      /* message when the user has selected this */
  3349.                   /* gadget, and when the user has released  */
  3350.                   /* it.                                     */ 
  3351.   STRGADGET,      /* GadgetType, a String gadget. */
  3352.   &my_border,     /* GadgetRender, a pointer to our Border */
  3353.                   /* structure.                            */
  3354.   NULL,           /* SelectRender, NULL since we do not    */
  3355.                   /* supply the gadget with an alternative */
  3356.                   /* image.                                */
  3357.   &my_text,       /* GadgetText, a pointer to our IntuiText */
  3358.                   /* structure.                             */
  3359.   NULL,           /* MutualExclude, no mutual exclude. */
  3360.   &my_string_info,/* SpecialInfo, a pointer to a StringInfo */
  3361.                   /* structure. */
  3362.   0,              /* GadgetID, no id. */
  3363.   NULL            /* UserData, no user data connected to the */
  3364.                   /* gadget.                                 */
  3365. };
  3366.  
  3367. The only difference between declaring and initializing a String gadget and an 
  3368. Integer gadget, is that when you initialize an Integer gadget you also need to:
  3369.  
  3370.  
  3371. 1. Set the flag LONGINT in the Activation field.
  3372. 2. Copy an integer string into the buffer string. eg: strcpy( my_buffer, "0" );
  3373.  
  3374. 4.6.3  USING A STRING/INTEGER GADGET
  3375.  
  3376. Once you have declared and initialized the appropriate structures Intuition 
  3377. takes care of everything else. While the user is entering a string he/she can 
  3378. even use some special keys:
  3379.  
  3380.   ------------------------------------------------------------
  3381.   | <-            Moves the cursor to the left.              |
  3382.   | ->            Moves the cursor to the right.             |
  3383.   | SHIFT and <-  Moves the cursor to the beginning of the   |
  3384.   |               string.                                    |
  3385.   | SHIFT and ->  Moves the cursor to the end of the string. |
  3386.   | BACKSPACE     Deletes the character to the left of the   |
  3387.   |               cursor.                                    |
  3388.   | DEL           Deletes the character under the cursor.    |
  3389.   | AMIGA and Q   Undo the last changes of the string.       |
  3390.   | AMIGA and X   Clears the buffer string.                  |
  3391.   | RETURN        Releases the gadget. If we have set the    |
  3392.   |               activation flag RELVERIFY we will receive  |
  3393.   |               a message telling us that the user has     |
  3394.   |               finished.                                  |
  3395.   ------------------------------------------------------------
  3396.  
  3397. 4.7  PROPORTIONAL GADGET
  3398.  
  3399. A proportional gadget is roughly a knob which can be moved horizontally, 
  3400. vertically or both inside a container. It can be like a volume control on a 
  3401. radio, or it can be used to show the user how much more data there exist in the 
  3402. file etc.
  3403.  
  3404. 4.7.1  PROPINFO STRUCTURE
  3405.  
  3406. The PropInfo structure look like this:
  3407.  
  3408. struct PropInfo
  3409. {
  3410.   USHORT Flags;
  3411.   USHORT HorizPot;
  3412.   USHORT VertPot;
  3413.   USHORT HorizBody;
  3414.   USHORT VertBody;
  3415.   USHORT CWidth;
  3416.   USHORT CHeight;
  3417.   USHORT HPotRes, VPotRes;
  3418.   USHORT LeftBorder;
  3419.   USHORT TopBorder;
  3420. };
  3421.  
  3422. Flags:
  3423.     
  3424. You normally should set one or both of the following two bits:
  3425.  
  3426.     
  3427. FREEHORIZ      Set this bit if you want the user to be able to move the knob 
  3428. horizontally.
  3429.     
  3430. FREEVERT       Set this bit if you want the user to be able to move the knob 
  3431. vertically.
  3432.                    
  3433.     
  3434. AUTOKNOB       Set this bit if you want that the size of the knob to be 
  3435. controlled by Intuition. (HorizBody and VertBody affects the size of the 
  3436. Autoknob.)
  3437.  
  3438.     
  3439. - If you want to use Intuition's Autoknob you should give GadgetRender a 
  3440. pointer to an Image structure. (You do not need to initialize the Image 
  3441. structure since Intuition takes care of it.)
  3442.  
  3443.     
  3444. - If you on the other hand would like to use your own knob image, you give 
  3445. GadgetRender a pointer to your Image structure, which you have initialized 
  3446. yourself.
  3447.  
  3448.     
  3449. PROPBORDERLESS Set this bit if you do not want any border around the container. 
  3450.  
  3451.  
  3452.     
  3453. KNOBHIT        This is a flag which is set by Intuition if this gadget is 
  3454. selected.
  3455.  
  3456. HorizPot:
  3457.     
  3458. This variable contains the actual (horizontally) proportional value. If the 
  3459. user has moved the knob 25% to the right, HorizPot is 25% of MAXPOT (0xFFFF). 
  3460. (0xFFFF * 0.25 = 0x3FFF)
  3461.  
  3462. VertPot:
  3463.     
  3464. Same as HorizPot except that this is the
  3465.     
  3466. vertically proportional value.
  3467.  
  3468. HorizBody:
  3469.     
  3470. Describes how much HorizPot should change every time the user clicks inside the 
  3471. container. If the volume of a melody can be between 0-63 (64 steps), HorizPot 
  3472. should change 1/64 each time. The HorizBody should therefore be initialized to: 
  3473.  
  3474.     
  3475. 1/64 * MAXBODY (0xFFFF) == 3FF
  3476.  
  3477.     
  3478. HorizBody describes also how much the user can see/use of the entire data. For 
  3479. example, if you have a list of 32 file names, and the user only can see 8 names 
  3480. at one time (25%), the knob (AUTOKNOB) should fill 25% of the container. 
  3481. HorizBody should in this case be initialized to:
  3482.     
  3483. MAXBODY * 8 / 32 (25% of 0xFFFF) == 3FFFF
  3484.  
  3485. VertBody:
  3486.     
  3487. Same as HorizBody except that it affects VertPot, and the vertical size of the 
  3488. knob (AUTOKNOB).
  3489.  
  3490. These variables are initialized and maintained by Intuition:
  3491.  
  3492. CWidth:
  3493.     
  3494. Width of the container.
  3495.  
  3496. CHeight:
  3497.     
  3498. Height of the container.
  3499.  
  3500. HPotRes, VPotRes:
  3501.     
  3502. Pot increments.
  3503.  
  3504. LeftBorder:
  3505.     
  3506. Position of the container's left border.
  3507.  
  3508. TopBorder:
  3509.     
  3510. Position of the container's top border.
  3511.  
  3512. 4.7.2  INITIALIZE A PROPORTIONAL GADGET
  3513.  
  3514. This is an example of how you can initialize a proportional gadget which can, 
  3515. for example, be used to change the volume of a melody (64 positions):
  3516. /* We need to declare an Image structure for the knob, but */
  3517. /* since Intuition will take care of the size etc of the   */
  3518. /* knob, we do not need to initialize the Image structure: */
  3519. struct Image my_image;
  3520.  
  3521. struct PropInfo my_prop_info=
  3522. {
  3523.   FREEHORIZ|      /* Flags, the knob should be moved         */
  3524.   AUTOKNOB,       /* horizontally, and Intuition should take */
  3525.                   /* care of the knob image.                 */
  3526.   0,              /* HorizPot, start position of the knob. */
  3527.   0,              /* VertPot, 0 since we will not move the */
  3528.                   /* knob vertically. */
  3529.   MAXBODY * 1/64, /* HorizBody, 64 steps. */
  3530.   0,              /* VertBody, 0 since we will not move the */
  3531.                   /* knob vertically. */
  3532.  
  3533.   /* These variables are initialized and maintained by */
  3534.   /* Intuition:                                        */
  3535.  
  3536.   0,              /* CWidth */
  3537.   0,              /* CHeight */
  3538.   0, 0,           /* HPotRes, VPotRes */
  3539.   0,              /* LeftBorder */
  3540.   0               /* TopBorder */
  3541. };
  3542.  
  3543. struct Gadget my_gadget=
  3544. {
  3545.   NULL,            /* NextGadget, no more gadgets. */
  3546.   80,              /* LeftEdge, 80 pixels out. */
  3547.   30,              /* TopEdge, 30 lines down. */
  3548.   200,             /* Width, 200 pixels wide. */
  3549.   12,              /* Height, 12 pixels lines high. */
  3550.   GADGHCOMP,       /* Flags, no highlighting. */
  3551.   GADGIMMEDIATE|   /* Activation, our program will receive a  */
  3552.   RELVERIFY,       /* message when the user has selected this */
  3553.                    /* gadget, and when the user has released  */
  3554.                    /* it.                                     */
  3555.   PROPGADGET,      /* GadgetType, a Proportional gadget. */
  3556.   &my_image,       /* GadgetRender, a pointer to our Image */
  3557.                    /* structure. (Intuition will take care */
  3558.                    /* of the knob image. See chapter 3     */
  3559.                    /* GRAPHICS for more information about  */
  3560.                    /* images.)                             */
  3561.   NULL,            /* SelectRender, NULL since we do not    */
  3562.                    /* supply the gadget with an alternative */
  3563.                    /* image.                                */
  3564.   &my_text,        /* GadgetText, pointer to a IntuiText */
  3565.                    /* structure. */
  3566.   NULL,            /* MutualExclude, no mutual exclude. */
  3567.   &my_prop_info,   /* SpecialInfo, pointer to a PropInfo */
  3568.                    /* structure. */
  3569.   0,               /* GadgetID, no id. */
  3570.   NULL             /* UserData, no user data connected to */
  3571.                    /* the gadget. */
  3572. };
  3573.  
  3574. 4.8  MONITORING THE GADGETS
  3575.  
  3576. Once you have decided which gadgets to use and what they should look like, it 
  3577. is time to decide what information they should send to your program. You need 
  3578. to decide if they should send a message when the user has selected them, or 
  3579. when the user has released them etc. All this work with handling the input can 
  3580. be easily done with help of Intuition's IDCMP system. IDCMP stands for 
  3581. Intuition's Direct Communications Message Ports system. Hard name but very easy 
  3582. to use.
  3583.  
  3584. The IDCMP system is also explained, in more detail, in chapter 8 IDCMP. 
  3585.  
  3586. If you want to use the IDCMP system you only need to follow these steps:
  3587.  
  3588. 1. Decide what events your gadget should report. You do it by setting the 
  3589. appropriate flags in the Activation field in the Gadget structure:
  3590.    
  3591.     
  3592. GADGIMMEDIATE  Set this flag if you want your program to receive a message 
  3593. immediately when the user selects this gadget.
  3594.  
  3595.     
  3596. RELVERIFY      Set this flag if you want your program to receive a message when 
  3597. the user releases (while still pointing at it) this gadget. If the user 
  3598. releases the gadget after having moved the pointer away from the select box, 
  3599. your program will not receive any message.
  3600.  
  3601.     
  3602. FOLLOWMOUSE    Set this flag if you want your program to receive a message 
  3603. every time the mouse is moved while this gadget is selected. 
  3604.  
  3605. 2. If the gadgets are connected to a window you need to tell Intuition which 
  3606. messages should be sent to your program. You do it by setting the appropriate 
  3607. flags in the IDCMPFlags field in the NewWindow structure:
  3608.  
  3609.     
  3610. GADGETDOWN     If a gadget connected to a window has the GADGIMMEDIATE flag 
  3611. set, you should set the GADGETDOWN flag.
  3612.  
  3613.     
  3614. GADGETUP       If a gadget connected to a window has the RELVERIFY flag set, 
  3615. you should set the GADGETUP flag.
  3616.  
  3617.     
  3618. MOUSEMOVE      If a gadget connected to a window has the FOLLOWMOUSE flag set, 
  3619. you should set the MOUSEMOVE flag.
  3620.  
  3621.     
  3622. CLOSEWINDOW    If you have connected the Close window gadget (System gadget) to 
  3623. your window, you can set this bit, and your program will receive a message when 
  3624. the user selects this gadget. Remember, Intuition does not close the window 
  3625. automatically when the user clicks on the Close window gadget. It is up to your 
  3626. program to decide what to do when you receive a CLOSEWINDOW event. (See 
  3627. Example1)
  3628.  
  3629. 3. Once your program is running it is time to try to collect and examine the 
  3630. messages sent to us by Intuition. One very commonly used way of doing it is to 
  3631. put the program to sleep [ Wait() ] and it will wake first when a message has 
  3632. arrived. We will then try to collect it [ GetMsg() ], and then (if success) 
  3633. examine the message. When we are finished with it we send it back [ ReplyMsg() 
  3634. ] so Intuition can send us another message if there is one. We can then put the 
  3635. program to sleep again, and so on.
  3636.    
  3637. When we collect a message with help of the function GetMsg() we actually 
  3638. receive a pointer to an IntuiMessage structure or NULL if there was nothing for 
  3639. us. The IntuiMessage structure looks like this:
  3640.  
  3641. struct IntuiMessage
  3642. {
  3643.   struct Message ExecMessage;
  3644.   ULONG Class;
  3645.   USHORT Code;
  3646.   USHORT Qualifier;
  3647.   APTR IAddress;
  3648.   SHORT MouseX, MouseY;
  3649.   ULONG Seconds, Micros;
  3650.   struct Window *IDCMPWindow;
  3651.   struct IntuiMessage *SpecialLink;
  3652. };
  3653.  
  3654. This structure is fully explained in chapter 8 IDCMP, so you do not need to 
  3655. bother so much about it for the moment. However, there are two variables in the 
  3656. structure that we need to understand. They are:
  3657.  
  3658. Class:
  3659.     
  3660. When a message is sent this field contains the reason why it was sent. It 
  3661. contains an IDCMP flag which tells us what has happened. For example, if the 
  3662. user has selected a gadget with the GADGIMMEDIATE flag set, this variable is 
  3663. equal to GADGETDOWN.
  3664.  
  3665. IAddress:
  3666.     
  3667. This is a pointer to the gadget (or similar) which sent the message. For 
  3668. example, if a program receives a message telling us that a gadget was selected, 
  3669. we need to know which gadget since there may be several gadget connected to the 
  3670. same window. This pointer points to that gadget.
  3671.  
  3672. Here is an example of a program which collects IDCMP messages:
  3673.  
  3674. main()
  3675. {
  3676.   /* Declare a variable in which we will store the IDCMP */
  3677.   /* flag: */
  3678.   ULONG class;
  3679.   
  3680.   /* Declare a pointer in which we will store the address */
  3681.   /* of the object (gadget) which sent the message: */
  3682.   APTR address;
  3683.  
  3684.   /* Declare a pointer to an IntuiMessage structure: */
  3685.   struct IntuiMessage *my_message;
  3686.  
  3687.  
  3688.   /* ... */
  3689.  
  3690.  
  3691.   /* (This is an endless loop) */
  3692.   while( TRUE )
  3693.   {
  3694.     /* 1. Put our program to sleep, and wake up first when   */
  3695.     /*    we have received a message. Do not bother for the  */
  3696.     /*    moment about all these funny thing we put inside   */
  3697.     /*    the Wait () function. I will talk about that later */
  3698.     /*    on.                                                */
  3699.     
  3700.     /* Wait until we have received a message: */
  3701.     Wait( 1 << my_window->UserPort->mp_SigBit );
  3702.  
  3703.  
  3704.  
  3705.     /* 2. We have now received a message and we shall now     */
  3706.     /*    try to collect it. If success the function GetMsg() */
  3707.     /*    will return a pointer to an IntuiMessage            */
  3708.     /*    structure, otherwise it will return NULL.           */
  3709.    
  3710.     /* Collect the message: */
  3711.     my_message = GetMsg( my_window->UserPort );
  3712.  
  3713.  
  3714.  
  3715.     /* 3. If we have collected a message successfully we save */
  3716.     /*    some important values which we later can use.       */
  3717.     
  3718.     if( my_message )
  3719.     {
  3720.       /* Save the code variable: */
  3721.       class = my_message->Class;
  3722.       
  3723.       /* Save the address of the gadget: */
  3724.       address = my_message->IAddress;
  3725.  
  3726.  
  3727.       /* 4. After we have saved all important values we     */
  3728.       /*    reply as fast as possible. Once we have replied */
  3729.       /*    we can NOT use the IntuiMessage structure any   */
  3730.       /*    more!                                           */
  3731.       
  3732.       ReplyMsg( my_message );
  3733.  
  3734.   
  3735.       /* 5. We can now check what message was sent to us. */
  3736.  
  3737.       /* Check which IDCMP flag was sent: */
  3738.       switch( class )
  3739.       {
  3740.         case GADGETDOWN: /* The user has selected a gadget: */
  3741.                
  3742.                /* If we want to check which gadget sent the */
  3743.                /* message we simply need to check the       */
  3744.                /* address pointer:                          */
  3745.                
  3746.                if( address == &my_first_gadget)
  3747.                  /* The gadget "my_first_gadget" selected. */
  3748.                  /* Do what ever you want... */
  3749.  
  3750.                if( address == &my_second_gadget)
  3751.                  /* The gadget "my_second_gadget" selected. */
  3752.                  /* Do what ever you want... */
  3753.  
  3754.                break;
  3755.  
  3756.         case GADGETUP: /* The user has released a gadget: */
  3757.                /* Do what ever you want... */
  3758.                break;
  3759.  
  3760.         case MOUSEMOVE: /* The user has moved the mouse */
  3761.                         /* while a gadget was selected. */
  3762.                /* Do what ever you want... */
  3763.                break;
  3764.  
  3765.         case CLOSEWINDOW: /* The user has selected the close */
  3766.                           /* window gadget. Time to quit.    */
  3767.                /* Do what ever you want... */
  3768.                break;
  3769.       }
  3770.     }
  3771.   }
  3772.  
  3773.   
  3774.   /* ... */
  3775. }   
  3776.  
  3777. 4.9  FUNCTIONS
  3778.  
  3779. Here are some commonly used functions:
  3780.  
  3781. ActivateGadget()
  3782.  
  3783. This function is used to activate a string or integer gadget,   although other 
  3784. gadgets too can be activated (selected) with this function. This function can 
  3785. be used to make it easier for the user to input text or values. Since the 
  3786. function will automatically activate (select) a specified gadget can the user 
  3787. continue to keep his/her fingers on the keyboard and does not have to fiddle 
  3788. around with the mouse each time he/she wants to input some values.
  3789.  
  3790.   Synopsis:
  3791.     
  3792. ActivateGadget( gadget, window, requester );
  3793.  
  3794.   gadget:
  3795.     
  3796. (struct Gadget *) Pointer to the gadget which should be selected.
  3797.  
  3798.   window:
  3799.     
  3800. (struct Window *) Pointer to the window which the gadget is connected to.
  3801.   
  3802.   requester:
  3803.     
  3804. (struct Requester *) If the gadget is connected to a requester, set this 
  3805. pointer to point to that requester, else NULL. Important, if this gadget is 
  3806. connected to a requester, it must be displayed when you execute this command! 
  3807. (See chapter 5 REQUESTERS for more information about requesters.)
  3808.  
  3809. ActivateWindow()
  3810.  
  3811. This function is used to activate a specified window.
  3812.  
  3813. Synopsis:
  3814.     
  3815. ActivateWindow( window );
  3816.   
  3817. window:
  3818.     
  3819. (struct Window *) Pointer to the window which should be activated. Note! The 
  3820. window must be open when you call the function!
  3821.  
  3822. RefreshGadgets()
  3823.  
  3824. This function redraws all the gadgets in the list, starting by the specified 
  3825. gadget. If you for example have added or deleted a gadget you need to call this 
  3826. function to see the changes. On the other hand, if you have changed the imagery 
  3827. of a gadget, or the gadget's image has been trashed by something, you can also 
  3828. use this function to refresh the display.
  3829.   
  3830. Synopsis:
  3831.     
  3832. RefreshGadgets( gadget, window, requester);
  3833.  
  3834. gadget:
  3835.     
  3836. (struct Gadget *) Pointer to the gadget where the redrawing should start. This 
  3837. gadget, and all the following gadgets in the list will be redrawn.
  3838.  
  3839. window:
  3840.     
  3841. (struct Window *) Pointer to the window which the gadgets are connected to.
  3842.   
  3843. requester:
  3844.     
  3845. (struct Requester *) If the gadget is connected to a requester, set this 
  3846. pointer to point to that requester, else NULL. Important, if this gadget is 
  3847. connected to a requester, it must be displayed when you execute this command! 
  3848. (See chapter 5 REQUESTERS for more information about requesters.)
  3849.  
  3850. AddGadget()
  3851.  
  3852. This function adds a gadget to the gadget list.
  3853.  
  3854. Synopsis:
  3855.     
  3856. result = AddGadget( window, gadget, position );
  3857.   
  3858. result:
  3859.     
  3860. (long) The actual position of the gadget when it has been added.
  3861.  
  3862. window:
  3863.     
  3864. (struct Window *) Pointer to the window, to which the gadget should be added.
  3865.  
  3866. gadget:
  3867.     
  3868. (struct Gadget *) Pointer to the gadget which will be added.  
  3869.  
  3870. position:
  3871.     
  3872. (long) Position in the gadget list. (Starts from zero). Eg:
  3873.     
  3874. 0 -> Before all other gadgets.
  3875.     
  3876. 1 -> After the first gadget, but before the second.
  3877.     
  3878. If a too big value is entered (or -1), the gadget will be placed last in the 
  3879. list.
  3880.  
  3881. Important, after your program has added the necessary gadgets, you need to call 
  3882. the function RefreshGadgets() in order to see your changes. You may add (or 
  3883. take away) several gadgets, but when you are finished you must call that 
  3884. function.
  3885.  
  3886. RemoveGadget()
  3887.  
  3888. This function removes a gadget from the list:
  3889.   
  3890. Synopsis:
  3891.     
  3892. result = RemoveGadget( window, gadget );
  3893.  
  3894. result:
  3895.     
  3896. (long) The position of the removed gadget or -1 if something went wrong.
  3897.  
  3898. window:
  3899.     
  3900. (struct Window *) Pointer to the window that the gadget is connected to.
  3901.  
  3902. gadget:
  3903.     
  3904. (struct Gadget *) Pointer to the gadget which will be removed.  
  3905.  
  3906. Important, after your program has removed the necessary gadgets, you need to 
  3907. call the function RefreshGadgets() in order to see your changes. You may take 
  3908. away (or add) several gadgets, but when you are finished you must call that 
  3909. function.
  3910.  
  3911. OnGadget()
  3912.  
  3913. This function enables a gadget (removes the GADGDISABLED bit in the gadget 
  3914. structure's Flags field):
  3915.   
  3916. Synopsis:
  3917.     
  3918. OnGadget( gadget, window, requester );
  3919.  
  3920. gadget:
  3921.     
  3922. (struct Gadget *) Pointer to the gadget which will be enabled.
  3923.  
  3924. window:
  3925.     
  3926. (struct Window *) Pointer to the window that the gadget is attached to.
  3927.   
  3928. requester:
  3929.     
  3930. (struct Requester *) If the gadget is connected to a requester, set this 
  3931. pointer to point to that requester, else NULL. Important, if this gadget is 
  3932. connected to a requester, it must be displayed when you execute this command!
  3933.  
  3934. Remember, as long as the gadget is disabled the user can not select it, and it 
  3935. will not broadcast any messages. A disabled gadget is drawn as usual except 
  3936. that it "ghosted".
  3937.  
  3938. OffGadget()
  3939.  
  3940. This function disables a gadget (sets the GADGDISABLED bit in the gadget 
  3941. structure's Flags field):
  3942.   
  3943. Synopsis:
  3944.     
  3945. OffGadget( gadget, window, requester );
  3946.  
  3947. gadget:
  3948.     
  3949. (struct Gadget *) Pointer to the gadget which will be disabled.
  3950.  
  3951. window:
  3952.     
  3953. (struct Window *) Pointer to the window that the gadget is attached to.
  3954.  
  3955. requester:
  3956.     
  3957. (struct Requester *) If the gadget is connected to a requester, set this 
  3958. pointer to point to that requester, else NULL. Important, if this gadget is 
  3959. connected to a requester, it must be displayed when you execute this command!
  3960.  
  3961. ModifyProp()
  3962.  
  3963. This function modifies a proportional gadget's values and knob. For example, if 
  3964. your program is reading files from the disk, VertBody was maybe equal to 0xFFFF 
  3965. (MAXBODY) in the beginning, but as more files are collected from the disk, you 
  3966. maybe want to change the size of the knob etc. You then simply call this 
  3967. function and it will change the values as well as redraw the gadget.
  3968.   
  3969. Synopsis:
  3970.     
  3971. ModifyProp( gadget, window, requester, flags, horiz_pot, vert_pot, horiz_body, 
  3972. vert_body ); 
  3973.  
  3974. gadget:
  3975.     
  3976. (struct Gadget *) Pointer to the proportional gadget which should be changed 
  3977. and redrawn.
  3978.  
  3979. window:
  3980.     
  3981. (struct Window *) Pointer to the window which the proportional gadget is 
  3982. connected to.
  3983.   
  3984. requester:
  3985.     
  3986. (struct Requester *) If the gadget is connected to a requester, set this 
  3987. pointer to point to that requester, else NULL. Important, if this gadget is 
  3988. connected to a requester, it must be displayed when you execute this command!
  3989.  
  3990. flags:
  3991.     
  3992. (long) Here is the list of all flags you may use:
  3993.   
  3994.     
  3995. FREEHORIZ      Set this bit if you want the user to be able to move the knob 
  3996. horizontally.
  3997.  
  3998.     
  3999. FREEVERT       Set this bit if you want the user to be able to move the knob 
  4000. vertically.
  4001.  
  4002.     
  4003. AUTOKNOB       Set this bit if you want that the size of the knob to be 
  4004. controlled by Intuition. (HorizBody and VertBody affects the size of the 
  4005. Autoknob.)
  4006.  
  4007.     
  4008. - If you want to use Intuition's Autoknob you should give GadgetRender a 
  4009. pointer to an Image structure. (You do not need to initialize the Image 
  4010. structure since Intuition takes care of it.)
  4011.  
  4012.     
  4013. - If you on the other hand would like to use your own knob image, you give 
  4014. GadgetRender a pointer to your Image structure, which you have initialized 
  4015. yourself.
  4016.  
  4017.     
  4018. PROPBORDERLESS Set this bit if you do not want any border around the container. 
  4019.  (See chapter 4.7 for more information.)
  4020.  
  4021. horiz_pot:
  4022.     
  4023. (long) This variable contains the actual (horizontally) proportional value. If 
  4024. the knob should be moved 25% to the right, HorizPot should be set to 25% of 
  4025. MAXPOT (0xFFFF). (0xFFFF * 0.25 = 0x3FFF)
  4026.  
  4027. vert_pot:
  4028.     
  4029. (long) Same as HorizPot except that this is the vertically proportional value.
  4030.  
  4031. horiz_body:
  4032.     
  4033. (long) Describes how much HorizPot should change every time the user clicks 
  4034. inside the container. If the volume of a melody can be between 0-63 (64 steps), 
  4035. HorizPot should change 1/64 each time. The HorizBody should therefore be set 
  4036. to:
  4037.     
  4038. 1/64 * MAXBODY (0xFFFF) == 3FF
  4039.  
  4040.     
  4041. HorizBody describes also how much the user can see/use of the entire data. For 
  4042. example, if you have a list of 32 file names, and the user only can see 8 names 
  4043. at one time (25%), the knob (AUTOKNOB) should fill 25% of the container. 
  4044. HorizBody should in this case be set to: MAXBODY * 8 / 32 (25% of 0xFFFF) == 
  4045. 3FFFF
  4046.  
  4047. vert_body:
  4048.     
  4049. Same as HorizBody except that it affects VertPot, and the vertical size of the 
  4050. knob (AUTOKNOB).
  4051.  
  4052. 4.10  EXAMPLES
  4053.  
  4054. Example 1
  4055. This program will open a normal window which is connected to the Workbench 
  4056. Screen. The window will use all System Gadgets, and will close first when the 
  4057. user has selected the System gadget Close window. (Same as Example3 in chapter 
  4058. 2 WINDOWS, except that we have added an IDCMP check on the Close window 
  4059. gadget.)
  4060.  
  4061. Example 2
  4062. Same as Example 1 except that we have added a Boolean gadget with the text 
  4063. "PRESS ME".
  4064.  
  4065. Example 3
  4066. Same as Example 2 except that the on/off state of the gadget is toggled each 
  4067. time the user hits the gadget.
  4068.  
  4069. Example 4
  4070. This program will open a normal window which is connected to the Workbench 
  4071. Screen. The window will use all System Gadgets, and will close first when the 
  4072. user has selected the System gadget Close window. Inside the window we have put 
  4073. two Boolean gadgets with the text "GADGET 1" and GADGET 2".
  4074.  
  4075. Example 5
  4076. This program will open a normal window which is connected to the Workbench 
  4077. Screen. The window will use all System Gadgets, and will close first when the 
  4078. user has selected the System gadget Close window. Inside the window we have put 
  4079. a Boolean gadget with two Image structures connected to it. Each time the user 
  4080. clicks on the gadget it will change images, lamp on/lamp off.
  4081.  
  4082. Example 6
  4083. This program will open a normal window which is connected to the Workbench 
  4084. Screen. The window will use all System Gadgets, and will close first when the 
  4085. user has selected the System gadget Close window. Inside the window we have put 
  4086. a Boolean gadget with a connecting mask. The gadget will only be highlighted 
  4087. when the user selects this gadget while pointing inside the specified (masked) 
  4088. area.
  4089.  
  4090. Example 7
  4091. This program will open a normal window which is connected to the Workbench 
  4092. Screen. The window will use all System Gadgets, and will close first when the 
  4093. user has selected the System gadget Close window. Inside the window we have put 
  4094. a String gadget.
  4095.  
  4096. Example 8
  4097. Same as Example 7 except that it is an Integer gadget.
  4098.  
  4099. Example 9
  4100. Same as Example 7 except that it is a Proportional gadget.
  4101.  
  4102. Example 10
  4103. Same as Example 9 except that the Proportional gadget uses a custom image knob.
  4104.  
  4105. Example 11
  4106. This program will open a normal window which is connected to the Workbench 
  4107. Screen. The window will use all System Gadgets, and will close first when the 
  4108. user has selected the System gadget Close window. Inside the window we have put 
  4109. a Proportional gadget where the knob can be moved both horizontally and 
  4110. vertically.
  4111.  
  4112. Example 12
  4113. This program will open a SuperBitmap window which is connected to the Workbench 
  4114. Screen. The window will use all System Gadgets, and will close first when the 
  4115. user has selected the System gadget Close window. Inside the window we have put 
  4116. two Proportional gadgets, one on the right side, and one at the bottom. With 
  4117. help of these two gadgets, the user can move around the BitMap.
  4118.  
  4119. This example is for experienced programmers only, since it uses some functions 
  4120. etc which we have not discussed yet. I have, however, included it here since it 
  4121. is a good example on how you can combine Proportional gadgets with SuperBitmap 
  4122. windows.
  4123.  
  4124. Example 13
  4125. This example demonstrates how to use six string gadgets which are automatically 
  4126. activated (selected) when the user release the gadget above.
  4127.  
  4128.  
  4129. REQUESTERS
  4130.  
  4131. 5.1  INTRODUCTION
  4132.  
  4133. Requesters are boxes filled with some sort of information which the user need 
  4134. to respond to. It can be as simple as a question to insert a disk in the 
  4135. internal drive, or a fully functional file requester. Requesters are like small 
  4136. windows with some gadgets connected to it, and they will first disappear when 
  4137. the user has "satisfied the request".
  4138.  
  4139. 5.2  DIFFERENT TYPES OF REQUESTERS
  4140.  
  4141. There exist three different types of requesters:
  4142. - System requesters
  4143. - Application requesters
  4144. - Double-menu requesters
  4145.  
  4146. 5.2.1  SYSTEM REQUESTERS
  4147.  
  4148. System requesters are opened and maintained by Intuition, and your program has 
  4149. no control over them. If the user, for example, is trying to load a file from 
  4150. drive df1:, and there is no disk present, the operating system would open the 
  4151. following request:
  4152.  
  4153.   -----------------------------------
  4154.   | System Request ============[*][*]
  4155.   -----------------------------------
  4156.   | No disk present              |  |
  4157.   | in unit  1                   |  |
  4158.   |                              |  |
  4159.   | ---------         ---------- |  |
  4160.   | | Retry |         | Cancel | |  |
  4161.   | ---------         ---------- |  |
  4162.   --------------------------------[*]
  4163.  
  4164. One important thing about System requesters is that they are like small 
  4165. windows. You can move around them, push them behind or in front of other 
  4166. windows/requesters, and resize them.
  4167.  
  4168. 5.2.2  APPLICATION REQUESTERS
  4169.  
  4170. This is the type of requester your program can open. They can be of any size 
  4171. (limited only by the size of the screen), and can be as simple or as 
  4172. complicated as you want.
  4173.  
  4174. If you only want a Yes/No (True/False) requester you can call the function 
  4175. AutoRequest(), and Intuition will open and take care of the rest. If you on the 
  4176. other hand want a more sophisticated requester you need to declare and 
  4177. initialize a Requester structure with your requirements, and call the function 
  4178. Request().
  4179.  
  4180. It is important to notice that an Application requester can not be moved 
  4181. around, resized etc (the window containing the requester can still, of course, 
  4182. be moved around and resized). It is only the System requesters, and the very 
  4183. simple requesters opened by the AutoRequest function, which acts like small 
  4184. windows.
  4185.  
  4186. There is also one other big difference. When an Application requester has been 
  4187. activated the user can no longer select gadgets connected to the window. The 
  4188. window has been "frozen". Eg. try Example4, and you will notice that you can 
  4189. not select the close-window gadget as long as the requester is active. On
  4190. the other hand, if a System requester has been activated, the user can still 
  4191. click on the close-window gadget, and a CLOSEWINDOW message is sent.
  4192.  
  4193. 5.2.3  DOUBLE-MENU REQUESTERS
  4194.  
  4195. Double-menu requesters are like normal Application requesters except that they 
  4196. will open first, and only, when the user double-clicks on the mouse menu 
  4197. button. To create a Double-menu requester you need to declare and initialize a 
  4198. Requester structure, and then call the function SetDMRequest(). Whenever the 
  4199. user from now on double-clicks on the menu button on the mouse, the requester 
  4200. will be opened. Call the function ClearDMRequest() when you do not want the 
  4201. user to be able to open the requester any more.
  4202.  
  4203. Only one DM-requester may be connected to each window.
  4204.  
  4205. 5.3  GRAPHICS FOR REQUESTERS
  4206.  
  4207. You can render a requester in two different ways. You can either tell Intuition 
  4208. what you want, and everything is rendered for you, or you can supply Intuition 
  4209. with your own customized Bitmap (which has been rendered by yourself).
  4210.  
  4211. If you want Intuition to draw the requester for you, you only need to decide 
  4212. what colour the background of the requester should be filled with, and declare 
  4213. and initialize one or more Border and IntuiText structures.
  4214.  
  4215. If you supply your own customized Bitmap Intuition will not draw anything 
  4216. itself. That means that all gadget connected to that requester does not need to 
  4217. have any Border/IntuiText/Image structures connected to them, since Intuition 
  4218. will not bother about them.
  4219.  
  4220. 5.4  POSITION
  4221.  
  4222. The requester can either be positioned relative to the top left corner of the 
  4223. window, or relative to the pointer position. If you want to position the 
  4224. requester relative to the window, you simply set the LeftEdge and TopEdge 
  4225. variables as desired. If you, on the other hand, want it relative to the 
  4226. pointer position, set the POINTREL flag, and initialize RelLeft and RelTop as 
  4227. desired.
  4228.  
  4229. 5.5  REQUESTERS AND GADGETS
  4230.  
  4231. When you create a requester, except when you call the function AutoRequest(), 
  4232. you need to connect at least one gadget to the requester. Gadgets connected to 
  4233. a requester works exactly the same as gadgets connected to a window but with 
  4234. two important differences:
  4235.  
  4236. 1. Every gadget connected to a requester MUST have the REQGADGET flag set in 
  4237. the GadgetType field.
  4238.  
  4239. 2. At least one gadget must satisfy the request, which means at least one 
  4240. gadget must have the ENDGADGET flag set in the Activation field. (Once a gadget 
  4241. with an ENDGADGET flag set is selected, the requester is satisfied, and will 
  4242. close.)
  4243.  
  4244. Remember that the user should always be able to find a safe way to leave the 
  4245. requester without affecting anything. The "way out gadget" (CANCEL, RESUME etc) 
  4246. should also always be placed on the right side in the requester. Here is an 
  4247. example:
  4248.  
  4249.  
  4250.   ---------------------------------------
  4251.   | System Request ================[*][*]
  4252.   ---------------------------------------
  4253.   | Do you really want to quit?      |  |
  4254.   |                                  |  |
  4255.   |                                  |  |
  4256.   | -------                   ------ |  |
  4257.   | | Yes |                   | No | |  |
  4258.   | -------                   ------ |  |
  4259.   ------------------------------------[*]
  4260.  
  4261. Note that the Yes/True/Retry button is always on the left side and that the 
  4262. No/False/Cancel button is always on the right side.
  4263.  
  4264. IMPORTANT! Make sure that the Gadgets are inside the requester, since Intuition 
  4265. will not do any boundary checking.
  4266.  
  4267. 5.6  SIMPLE REQUESTERS
  4268.  
  4269. If you just want a simple requester with a True/False (or just False) option, 
  4270. you can use the function AutoRequest(). You give Intuition some information 
  4271. about how the requester should look like (height, text etc), and Intuition 
  4272. takes care of everything else. It opens the requester, put your program to 
  4273. rest, and
  4274. when finished, returns a boolean value which tells your program what the user 
  4275. selected. If the user selected the left gadget (positive) it returns TRUE, and 
  4276. if the user selected the right gadget (negative) it returns FALSE.
  4277.  
  4278. Example:
  4279.  
  4280. result = AutoRequest( window, info_text, pos_text, neg_text,  pos_IDCMP, 
  4281. neg_IDCMP, width, height );
  4282.  
  4283. window:
  4284.     
  4285. Pointer to a window if there exist one, else NULL.
  4286.  
  4287. info_text:
  4288.     
  4289. Pointer to an IntuiText structure containing the "body text".
  4290.  
  4291. pos_text:
  4292.     
  4293. Pointer to an IntuiText structure containing the "positive text". Eg: "TRUE", 
  4294. "YES", "RETRY" etc. (Optional)
  4295.  
  4296. neg_text:
  4297.     
  4298. Pointer to an IntuiText structure containing the "negative text". Eg: "FALSE", 
  4299. "NO", "CANCEL" etc.
  4300.  
  4301. pos_IDCMP:
  4302.     
  4303. The IDCMP flags which satisfy the "positive" gadget. (The flag RELVERIFY is 
  4304. already set.)
  4305.  
  4306. pos_IDCMP:
  4307.     
  4308. The IDCMP flags which satisfy the "negative" gadget. (The flag RELVERIFY is 
  4309. already set.)
  4310.  
  4311. width:
  4312.     
  4313. How many pixels wide the requester should be.
  4314.  
  4315. height:
  4316.     
  4317. How many lines high the requester should be.
  4318.  
  4319.  
  4320.  
  4321. 5.7  OPEN A REQUESTER
  4322.  
  4323. If you want to use a more complicated requester instead of the Simple requester 
  4324. you need to:
  4325.  
  4326. 1. Declare and initialize a Requester structure with your requirements.
  4327.  
  4328. 2. Declare and initialize the Gadget structures which are going to be connected 
  4329. to the requester.
  4330.  
  4331. 3. Call the function Request() in order to display the requester as a normal 
  4332. requester, or call the function SetDMRequest() to enable the user to bring up 
  4333. the requester as a Double-menu requester.
  4334.  
  4335. 5.7.1  INITIALIZE A REQUESTER
  4336.  
  4337. If you want to use a requester you need to declare and initialize a Requester 
  4338. structure which look like this:
  4339.  
  4340. struct Requester
  4341. {
  4342.   struct Requester *OlderRequest;
  4343.   SHORT LeftEdge, TopEdge;
  4344.   SHORT Width, Height;
  4345.   SHORT RelLeft, RelTop;
  4346.   struct Gadget *ReqGadget;
  4347.   struct Border *ReqBorder;
  4348.   struct IntuiText *ReqText;
  4349.   USHORT Flags;
  4350.   UBYTE BackFill;
  4351.   struct Layer *ReqLayer;
  4352.   UBYTE ReqPad1[32];
  4353.   struct BitMap *ImageBMap;
  4354.   struct Window *RWindow;
  4355.   UBYTE ReqPad2[36];
  4356. };
  4357.  
  4358. OlderRequest:
  4359.     
  4360. Initialized and maintained by Intuition. Set to NULL.
  4361.  
  4362. LeftEdge, TopEdge:
  4363.     
  4364. Position of the requester relative to the top left corner of the window (if the 
  4365. POINTREL flag is not set).
  4366.  
  4367. Width, Height:
  4368.     
  4369. Size of the requester.
  4370.  
  4371. RelLeft, RelTop:
  4372.     
  4373. If the POINTREL flag is set, these values describes the position of the 
  4374. requester relative to the pointer.
  4375.  
  4376. ReqGadget:
  4377.     
  4378. Pointer to the first gadget in the linked list. Remember, there must exist at 
  4379. least one gadget connected to the requester with the ENDGADGET flag set.
  4380.  
  4381. ReqBorder:
  4382.     
  4383. Pointer to a Border structure used to render the requester.
  4384.  
  4385. ReqText:
  4386.     
  4387. Pointer to an IntuiText structure used to print text in the requester.
  4388.  
  4389. Flags:
  4390.     
  4391. There exist two flags which you may set:
  4392.  
  4393.     
  4394. POINTREL: Set this flag if you want to position the requester relative to the 
  4395. pointer. Set the RelLeft, RelTop as desired.
  4396.  
  4397.     
  4398. PREDRAWN: If you supply with your own customized Bitmap set this flag, and 
  4399. Intuition will not try to draw anything itself.
  4400.  
  4401.     
  4402. Intuition sets these flags:
  4403.                    
  4404.     
  4405. REQACTIVE:    This flag is set when the requester is activated, and cleared 
  4406. when the requester is closed (deactivated).
  4407.  
  4408.     
  4409. REQOFFWINDOW: This flag is set if the requester is active and positioned 
  4410. outside the window. (The user has maybe shrinked the window so it is smaller 
  4411. than you thought.)
  4412.  
  4413.     
  4414. SYSREQUEST:   This flag is set if the requester is of the type System 
  4415. requester.
  4416.  
  4417. BackFill:
  4418.     
  4419. Colour register used to fill the requester with before any drawing takes place. 
  4420. For example, if you want to render the graphics on an orange background, you 
  4421. set the BackFill field to 3 (orange, normal WB colours).
  4422.  
  4423. ReqLayer:
  4424.     
  4425. Pointer to the Layer structure for this requester. Initialized and maintained 
  4426. by Intuition. Set to NULL.
  4427.  
  4428. ReqPad1:
  4429.     
  4430. Initialized and maintained by Intuition. Set to NULL. (Used by the system.)
  4431.  
  4432. ImageBMap:
  4433.     
  4434. If the bit PREDRAWN is set, this field should contain a pointer to a customized 
  4435. Bitmap, else NULL.
  4436.  
  4437. RWindow:
  4438.     
  4439. Initialized and maintained by Intuition. Set to NULL. (Used by the system, 
  4440. points back to the Window which this requester is connected to.)
  4441.  
  4442. ReqPad2:
  4443.     
  4444. Initialized and maintained by Intuition. Set to NULL. (Used by the system.)
  4445.  
  4446. Here is an example of how to initialize a Requester structure:
  4447.  
  4448. struct Requester my_requester=
  4449. {
  4450.   NULL,             /* OlderRequester, used by Intuition.   */
  4451.   40, 20,           /* LeftEdge, TopEdge, 40 pixels out, 20 */
  4452.                     /* lines down.                          */
  4453.   320, 100,         /* Width, Height, 320 pixels wide, 100  */
  4454.                     /* lines high.                          */
  4455.   0, 0,             /* RelLeft, RelTop, Since POINTREL flag */
  4456.                     /* is not set, Intuition ignores these  */
  4457.                     /* values.                              */
  4458.   &my_first_gadget, /* ReqGadget, pointer to the first      */
  4459.                     /* gadget.                              */
  4460.   &my_border,       /* ReqBorder, pointer to a Border       */
  4461.                     /* structure.                           */
  4462.   &my_text,         /* ReqText, pointer to a IntuiText      */
  4463.                     /* structure.                           */
  4464.   NULL,             /* Flags, no flags set.                 */
  4465.   3,                /* BackFill, draw everything on an      */
  4466.                     /* orange background.                   */
  4467.   NULL,             /* ReqLayer, used by Intuition. Set to  */
  4468.                     /* NULL.                                */
  4469.   NULL,             /* ReqPad1, used by Intuition. Set to   */
  4470.                     /* NULL.                                */
  4471.   NULL,             /* ImageBMap, no predrawn Bitmap. Set   */
  4472.                     /* to NULL. (The PREDRAWN flag was not  */
  4473.                     /* set.)                                */
  4474.   NULL,             /* RWindow, used by Intuition. Set to   */
  4475.                     /* NULL.                                */
  4476.   NULL              /* ReqPad2, used by Intuition. Set to   */
  4477.                     /* NULL.                                */
  4478. };
  4479.  
  4480. If you would like to supply your own customized and predrawn Bitmap, instead of 
  4481. letting Intuition render the requester you need to:
  4482.  
  4483. 1. Set the flag PREDRAWN in the Flags field.
  4484.  
  4485. 2. Set the ImageBMap to point at your BitMap structure.
  4486.  
  4487. Remember that Intuition will now not draw anything for you. The ReqBorder, 
  4488. ReqText and BackFill variables are ignored, and should therefore be set to 
  4489. NULL. Intuition will also not render the gadgets connected to the requester. 
  4490. Because of this it is important that the rendering of the Bitmap is done 
  4491. carefully, and that the graphics correspond to where the gadgets are etc.
  4492.  
  4493. 5.7.2  HOW TO ACTIVATE AN APPLICATION REQUESTER
  4494.  
  4495. If you have declared and initialized a Requester structure you only need to 
  4496. call the function Request() in order to activate it.
  4497.  
  4498. Example:
  4499.  
  4500. result = Request( my_requester, my_window );
  4501.  
  4502. my_requester:
  4503.     
  4504. Pointer to the Requester structure.
  4505.  
  4506. my_window:
  4507.     
  4508. Pointer to the Window structure which the requester should be connected to.
  4509.  
  4510. result:
  4511.     
  4512. Boolean value returned. If Intuition could successfully open the requester the 
  4513. function returns TRUE, else (something went wrong, not enough memory etc) the 
  4514. function returns FALSE.
  4515.  
  4516. If you on the other hand would like the requester to be a Double-menu requester 
  4517. you should call the function SetDMRequest(), which will allow the user to 
  4518. activate the requester by double clicking the mouse menu button. 
  4519.  
  4520. Example:
  4521.  
  4522. result = SetDMRequest( my_window, my_requester );
  4523.  
  4524. my_window:
  4525.     
  4526. Pointer to the Window structure which the requester should be connected to.
  4527. my_requester: Pointer to the Requester structure.
  4528.  
  4529. result:
  4530.     
  4531. Boolean value returned. If Intuition could successfully open the requester the 
  4532. function returns TRUE, else (some thing went wrong, not enough memory or the a 
  4533. DM requester is already connected to the window etc) the function returns 
  4534. FALSE.
  4535.  
  4536. You can after you have called the SetDMRequest() function successfully, take 
  4537. away the ability for the user to open the requester by calling the function 
  4538. ClearDMRequest().
  4539.  
  4540. Example:
  4541.  
  4542. result = ClearDMRequest( my_window );
  4543.  
  4544. my_window:
  4545.     
  4546. Pointer to the Window structure which the requester is connected to.
  4547.  
  4548. result:
  4549.     
  4550. If the function could disable the user to activate the DM-requester it returns 
  4551. TRUE, else (something went wrong, the requester is in use etc) it returns 
  4552. FALSE.
  4553.  
  4554. 5.8  IDCMP FLAGS
  4555.  
  4556. There exist three IDCMP flags which are special for the requesters. When a 
  4557. requester is activated you can, if you want to, receive a message telling you 
  4558. that a requester was activated. This is especially useful if you are using 
  4559. Double-menu requesters, since this is the only way to check if the requester 
  4560. was opened.
  4561.  
  4562. If you want to get a message every time a requester is activated, you need to 
  4563. set the flag REQSET in the IDCMPFlags field in the NewWindow structure. Set the 
  4564. flag REQCLEAR if you want to receive a message every time a requester is 
  4565. deactivated. See Example5 for more details.
  4566.  
  4567. There exist also one special IDCMP flag called REQVERIFY. If you set this flag 
  4568. in the IDCMPFlags field in the NewWindow structure your program will receive a 
  4569. message when the user is trying to activate a Double-menu requester. The 
  4570. interesting thing about this flag is that the requester will not be opened 
  4571. until your program has replied, ReplyMsg(). Your program can therefore finish 
  4572. of something (like finish of with drawing something etc) before the requester 
  4573. is displayed, and when your program is ready, it can reply, and the requester 
  4574. is activated. See Example6 for more information.
  4575.  
  4576.  
  4577. 5.9 FUNCTIONS
  4578.  
  4579. Here are some commonly used functions:
  4580.  
  4581. AutoRequest()
  4582.  
  4583. This function opens a Simple requester. Intuition will automatically activate 
  4584. it and take care of the response from the user. It will return TRUE if the left 
  4585. gadget was selected, and FALSE if the right gadget was selected.
  4586.  
  4587. Synopsis:
  4588.     
  4589. result = AutoRequest( my_window, info_txt, pos_txt, neg_txt, pos_IDCMP, 
  4590. neg_IDCMP, width, height );
  4591.  
  4592. my_window:
  4593.     
  4594. (struct Window *) Pointer to a window if there exist one, else NULL.
  4595.  
  4596. info_txt:
  4597.     
  4598. (struct IntuiText *) Pointer to an IntuiText structure containing the "body 
  4599. text".
  4600.  
  4601. pos_txt:
  4602.     
  4603. (struct IntuiText *) Pointer to an IntuiText structure containing the "positive 
  4604. text". Eg: "TRUE", "YES", "RETRY" etc. (Optional)
  4605.  
  4606. neg_txt:
  4607.     
  4608. (struct IntuiText *) Pointer to an IntuiText structure containing the "negative 
  4609. text". Eg: "FALSE", "NO", "CANCEL" etc.
  4610.  
  4611. pos_IDCMP:
  4612.     
  4613. (long) IDCMP flags which satisfy the "positive" gadget. (The flag RELVERIFY is 
  4614. already set.)
  4615.  
  4616. pos_IDCMP:
  4617.     
  4618. (long) IDCMP flags which satisfy the "negative" gadget. (The flag RELVERIFY is 
  4619. already set.)
  4620.  
  4621. width:
  4622.     
  4623. (long) How many pixels wide the requester should be.
  4624.  
  4625. height:
  4626.     
  4627. (long) How many lines high the requester should be.
  4628.  
  4629. result:
  4630.     
  4631. (long) Boolean value. The function returns TRUE if the positive gadget was 
  4632. satisfied, and FALSE if the negative gadget was satisfied.
  4633.  
  4634. Request()
  4635.  
  4636. This function activates a requester connected to a window.
  4637.   
  4638. Synopsis:
  4639.     
  4640. result = Request( my_requester, my_window );
  4641.  
  4642. my_requester:
  4643.     
  4644. (struct Requester *) Pointer to the Requester structure.
  4645.  
  4646. my_window:
  4647.     
  4648. (struct Window *) Pointer to the Window structure which the requester should be 
  4649. connected to.
  4650.  
  4651. result:
  4652.     
  4653. (long) Boolean value returned. If Intuition could successfully open the 
  4654. requester the function returns TRUE, else (something went wrong, not enough 
  4655. memory etc) the function returns FALSE.
  4656.  
  4657. EndRequest()
  4658.  
  4659. This function deactivates a requester which has been activated.
  4660.   
  4661. Synopsis:
  4662.     
  4663. EndRequest( my_requester, my_window );
  4664.  
  4665. my_requester:
  4666.     
  4667. (struct Requester *) Pointer to the Requester structure which will be removed.
  4668.  
  4669. my_window:
  4670.     
  4671. (struct Window *) Pointer to the Window structure which the requester is 
  4672. connected to.
  4673.  
  4674. SetDMRequest()
  4675.  
  4676. This function allows the user to activate a Double-menu requester by clicking 
  4677. twice on the mouse menu button.
  4678.  
  4679. Synopsis:
  4680.     
  4681. result = SetDMRequest( window, requester );
  4682.  
  4683. window:
  4684.     
  4685. (struct Window *) Pointer to the Window structure which the requester should be 
  4686. connected to.
  4687.  
  4688. requester:
  4689.     
  4690. (struct Requester *) Pointer to the Requester structure.
  4691.  
  4692. result:
  4693.     
  4694. (long) Boolean value returned. If Intuition could successfully open the 
  4695. requester the function returns TRUE, else (something went wrong, not enough 
  4696. memory or a DM requester is already connected to the window, etc) the function 
  4697. returns FALSE.
  4698.  
  4699. ClearDMRequest()
  4700.  
  4701. This function disables a Double-menu requester. The user can not open the 
  4702. requester any more.
  4703.   
  4704. Synopsis:
  4705.     
  4706. result = ClearDMRequest( my_window );
  4707.  
  4708. my_window:
  4709.     
  4710. (struct Window *) Pointer to the Window structure which the requester is 
  4711. connected to. The DMRequest pointer in the Window structure is set to NULL.
  4712.  
  4713. result:
  4714.     
  4715. (long) If the function could disable the DM-requester it returns TRUE, else 
  4716. (something went wrong, the requester is in use etc) it returns FALSE.
  4717.  
  4718. 5.10  EXAMPLES
  4719.  
  4720. Example 1
  4721. This example opens a Simple requester by calling the function AutoRequest. It 
  4722. displays a message "This is a very simple requester!", and has only one gadget 
  4723. connected to it (on the right side of the requester) with the text "OK".
  4724.  
  4725. Example 2
  4726. Same as Example 1, except that the requester displays a message "Do you really 
  4727. want to quit?", and allows the user to choose between "Yes" and "No". The 
  4728. program  will continue to reopen the requester until the user has chosen "Yes".
  4729.  
  4730. Example 3
  4731. Same as Example 1, except that this requester displays a message "Insert a disk 
  4732. in any drive!", and allows the user to choose between "Yes" and "No". The 
  4733. program will continue to reopen the requester until the user has chosen "Yes" 
  4734. or inserted a disk.
  4735.  
  4736. Example 4
  4737. This program will open a normal window which is connected to the Workbench 
  4738. Screen. The window will use all System Gadgets, and will close first when the 
  4739. user has selected the System gadget Close window. Inside the window we have 
  4740. activated an Application requester with a connecting gadget. The requester will 
  4741. first be satisfied when the user has selected the gadget, and will then be 
  4742. deactivated. The window can now be closed.
  4743.  
  4744. Example 5
  4745. Same as Example 4, except that the requester is first activated when the user 
  4746. double-clicks on the right mouse button. This example shows how to create a 
  4747. Double-menu requester, and how to monitor the IDCMP flags REQSET and REQCLEAR.
  4748.  
  4749. Example 6
  4750. Same as Example 5, except that whenever the user double-clicks on the right 
  4751. mouse button, we will receive a REQVERIFY message, and first when we have 
  4752. replied, will the requester be activated. This example shows how to use the 
  4753. REQVERIFY flag.
  4754.  
  4755.  
  4756. Example 7
  4757. This program will open a normal window which is connected to the Workbench 
  4758. Screen. The window will use all System Gadgets, and will close first when the 
  4759. user has selected the System gadget Close window. Inside the window we have 
  4760. activated an Application requester with three connecting gadgets. Two are 
  4761. Boolean gadgets ("OK and "CANCEL"), and one is a String gadget.
  4762.  
  4763. Example 8
  4764. Same as Example 7, except that it is an Integer gadget.
  4765.  
  4766. Example 9
  4767. Same as Example 8, except that it is a Proportional gadget.
  4768.  
  4769. Example 10
  4770. This example demonstrates how you use a requester with a predrawn bitmap. This 
  4771. is very useful when you want colourful and catching requesters. The advantage 
  4772. with a special bitmap is that if the window which the requester is tied to is 
  4773. resized, the drawing will not be destroied.
  4774.  
  4775. The graphics data is stored in a separate file called "Example10Graphics.c". 
  4776. Both this and the graphical file should be compiled separately, then linked 
  4777. together. If you have a SAS (Lattice) C Compiler you would do like this:
  4778.  
  4779. lc Example10.c
  4780. lc Example10
  4781. Graphics.c
  4782. blink with Example10.lnk
  4783.  
  4784. This program will NOT try to erase the disk! It is ony a demonstration how to 
  4785. use a requester.
  4786.  
  4787.  
  4788. ALERTS
  4789.  
  4790. 6.1  INTRODUCTION
  4791.  
  4792. Alerts is the last resource your program can use in order to inform the user 
  4793. about a problem. When your program displays an alert all screens are moved 
  4794. down, and a black and red box is opened at the top of the display. It not only 
  4795. gives the user a hart attack, but it will also tell him/her what went wrong, 
  4796. and if there is a way out.
  4797.  
  4798. 6.2  DIFFERENT LEVELS OF WARNINGS 
  4799.  
  4800. There exist three levels of warnings:
  4801.  
  4802. 1. If you want to alert the user that something went wrong, but it is nothing 
  4803. serious, you can flash the screens. You do it by calling the function 
  4804. DisplayBeep(), and the background colour of all screens will be flashed.
  4805.  
  4806. 2. If something went wrong, and you want to inform the user, maybe even want 
  4807. that he/she does something, you should open a Requester. (Described in chapter 
  4808. 5 REQUESTERS.)
  4809.  
  4810. 3. If something went TERRIBLE WRONG, (the system is crashing etc) your program 
  4811. should activate an Alert message, DisplayAlert().
  4812.  
  4813. 6.3  HOW TO USE THE DISPLAYALERT() FUNCTION
  4814.  
  4815. Synopsis:
  4816.     
  4817. result = DisplayAlert( nr, message, height ); 
  4818.  
  4819. nr:
  4820.     
  4821. (long)  Value which describes if it is a RECOVERY_ALERT or a DEADEND_ALERT.
  4822.  
  4823. message:
  4824.     
  4825. (char *) Pointer to an array of characters (char). It contains the strings we 
  4826. want to display, and some extra information (position etc). The string itself 
  4827. is divided into substrings, which all contain information about its position 
  4828. etc.
  4829.           
  4830.     
  4831. Each substring consists of:
  4832.           
  4833.     
  4834. - 2 bytes (16-bit) which are used for the x position of the text.
  4835.     
  4836. - 1 byte (8-bit) which is used for the y position of the text.
  4837.     
  4838. - The text string which ends with a NULL ('\0') sign.
  4839.     
  4840. - A Continuation byte. If it is TRUE there is another substring after this one, 
  4841. else this was the last substring.
  4842.  
  4843.     
  4844. (See below for more information)
  4845.  
  4846. height:
  4847.     
  4848. (long) The height of the Alert box.
  4849.  
  4850. result:
  4851.     
  4852. (long) The function DisplayAlert() returns a boolean value. If it is a 
  4853. RECOVERY_ALERT and the user pressed the left mouse button it returns TRUE else, 
  4854. if the user pressed the right mouse button, it returns FALSE. If it is a 
  4855. DEADEND_ALERT the function will immediate return FALSE.
  4856.  
  4857.  
  4858.  
  4859. 6.4  EXAMPLES OF STRINGS AND SUBSTRINGS
  4860.  
  4861. If we want to display the following Alert message:
  4862.  
  4863. ---------------------------------------------------------------
  4864. |                                                             |
  4865. |  ERROR! Not enough memory!                                  |
  4866. |                                                             |
  4867. ---------------------------------------------------------------
  4868.  
  4869. the string would be declared and initialized like this:
  4870.  
  4871. /* Declare the array of char (the string): */
  4872. char message[30]; /* 30 bytes needed. */
  4873.  
  4874. /* Fill the string with the message: (Remember to give    */
  4875. /* space for the first 3 bytes which will contain the x/y */
  4876. /* position.)                                             */
  4877. strcpy( message, "   ERROR! Not enough memory!" );
  4878. /* The NULL sign is automatically placed at position 28. */
  4879.  
  4880. /* Fill the string with the position (x,y) (first 3 bytes)  */
  4881. message[0]=0;  /* X position is less than 256, therefore 0. */
  4882. message[1]=32; /* 32 pixels out. */
  4883. message[2]=16; /* 16 lines down. */
  4884.  
  4885. /* Set the Continuation byte to FALSE since there are no */
  4886. /* more substrings after this one:                       */
  4887. message[29]=FALSE;
  4888.  
  4889. If we on the other hand want to display the following Alert message:
  4890.  
  4891. ---------------------------------------------------------------
  4892. |                                                             |
  4893. |  ERROR! Not enough memory!                                  |
  4894. |                                                             |
  4895. |  Buy a memory expansion!                                    |
  4896. |                                                             |
  4897. ---------------------------------------------------------------
  4898.  
  4899. the string would be declared and initialized like this:
  4900.  
  4901. /* Declare the array of char (the string): */
  4902. char message[58]; /* 58 bytes needed. */
  4903.  
  4904. /* Fill the array with the first substring: (Remember to */
  4905. /* give space for the first 3 bytes which will contain   */
  4906. /* the x/y position.)                                    */
  4907. strcpy( message, "   ERROR! Not enough memory!" );
  4908.  
  4909. /* Add the second substring: (Remember this time to give */
  4910. /* space for 5 bytes in the beginning of the string.     */
  4911. /* They are used for the NULL sign which finish off the  */
  4912. /* first substring, the Continuation byte, and three     */
  4913. /* bytes for the position for the second substring.)     */
  4914. strcat( message, "     Buy a memory expansion!");
  4915. /* The NULL sign which finish of the second substring is */
  4916. /* automatically placed at position 56. */
  4917.  
  4918. /* Fill the first substring with the position (x,y) */
  4919. /* (first 3 bytes) */
  4920. message[0]=0;  /* X position is less than 256, therefore 0. */
  4921. message[1]=32; /* 32 pixels out. */
  4922. message[2]=16; /* 16 lines down. */
  4923.  
  4924. /* Add the NULL sign which finish of the first substring: */
  4925. /* (It was deleted when we connected the two strings with */
  4926. /* the strcat() function.)                                */ 
  4927. message[28]='\0';
  4928.  
  4929. /* Set the Continuation byte to TRUE which tells     */
  4930. /* Intuition that there is another substring coming: */
  4931. message[29]=TRUE;
  4932.   
  4933. /* Fill the second substring with the position (x,y): */
  4934. message[30]=0;  /* X position is less than 256. */
  4935. message[31]=32; /* 32 pixels out. */
  4936. message[32]=32; /* 32 lines down. */
  4937.  
  4938. /* Set the Continuation byte to FALSE since there are */
  4939. /* no more substrings after this one: */
  4940. message[57]=FALSE;
  4941.  
  4942. 6.5  FUNCTIONS
  4943.  
  4944. DisplayAlert()
  4945.  
  4946. This function activates an Alert message.
  4947.  
  4948. Synopsis:
  4949.     
  4950. result = DisplayAlert( nr, message, height ); 
  4951.  
  4952. nr:
  4953.     
  4954. (long)  Value which describes if it is a RECOVERY_ALERT or a DEADEND_ALERT.
  4955.  
  4956. message:
  4957.     
  4958. (char *) Pointer to an array of characters (char). It contains the strings we 
  4959. want to display, and some extra information (position etc). The string itself 
  4960. is divided into substrings, which all contain information about its position 
  4961. etc.
  4962.           
  4963.     
  4964. - 2 bytes (16-bit) which are used for the x position of the text.
  4965.     
  4966. - 1 byte (8-bit) which is used for the y position of the text.
  4967.     
  4968. - The text string which ends with a NULL ('\0') sign.
  4969.     
  4970. - A Continuation byte. If it is TRUE there is another substring after this one, 
  4971. else this was the last substring.
  4972.  
  4973. height:
  4974.     
  4975. (long) The height of the Alert box.
  4976.  
  4977. result:
  4978.     
  4979. (long) The function DisplayAlert() returns a boolean value. If it is a 
  4980. RECOVERY_ALERT and the user pressed the left mouse button it returns TRUE else, 
  4981. if the user pressed the right mouse button, it returns FALSE. If it is a 
  4982. DEADEND_ALERT the function will immediate return FALSE.
  4983.  
  4984. 6.6  EXAMPLES
  4985.  
  4986. Example 1
  4987. This example displays an Alert message at the top of the display.
  4988.  
  4989.  
  4990. MENUS
  4991.  
  4992. 7.1  INTRODUCTION
  4993.  
  4994. If you have been working on the Amiga you have probably used menus a lot. They 
  4995. are flexible tools which are easy to access and are not complicated to set up. 
  4996. In this chapter we will look at how you can create your own menus, how to use 
  4997. all the special features offered by Intuition, and how the communication 
  4998. between the user and the menus is executed.
  4999.  
  5000. 7.2  MENU DESIGN
  5001.  
  5002. You can connect a "menu strip" to every window, and when the user presses down 
  5003. the right mouse button, the active window's menu strip is shown at the top of 
  5004. the display.
  5005.  
  5006. An example of a "menu strip":
  5007.  
  5008. Project  Block  Windows  Search
  5009.  
  5010. The user can now move the pointer to one of the menu headings, while still 
  5011. holding the right mouse button pressed, and that menu's "item box" is 
  5012. displayed.
  5013.  
  5014. An example of a "item box":
  5015.  
  5016. PROJECT  Block  Windows  Search
  5017. |----------|
  5018. | Open     |
  5019. | Save     |
  5020. | Save as  |
  5021. | Print    |
  5022. | Info     |
  5023. | Quit     |
  5024. |----------|
  5025.  
  5026. The user can now choose the "menu item" he/she wants. The user does it by 
  5027. moving the pointer to the desired menu item, and releases the right mouse 
  5028. button. If the user wants he/she can pick several menu items at the same "menu 
  5029. action" by holding down the right mouse button as normal, but click with the 
  5030. left mouse button on each menu item the user wants to select. The user can also 
  5031. "drag" (holding both mouse buttons down) over several menu items if he/she 
  5032. wants to select all of them.
  5033.  
  5034. You can connect a separate menu to an item if you want. That menu is usually 
  5035. referred as "submenu", and it consists of one or more "subitems".
  5036.  
  5037. An Example of "subitems": (Note that the subitem box overlap the item box!)
  5038. Project  Block  Windows  Search
  5039. |----------|
  5040. | Open     |
  5041. | Save     |
  5042. | Save a--------------
  5043. | PRINT | to printer |
  5044. | Info  | to a file  |
  5045. | Quit  --------------
  5046. |----------|
  5047. 7.3  HOW TO ACCESS MENUS FROM THE KEYBOARD
  5048.  
  5049. If you want you can allow the user to select certain menu items from the 
  5050. keyboard. This is very handy if it is a command the user will often use, and 
  5051. you want to provide him/her with a shortcut. The user can access the menu item 
  5052. by pressing the right "Amiga key" + another key. For example, if the user 
  5053. should
  5054. be able to access the menu item "Open" from the keyboard by pressing the "Amiga 
  5055. key" + "O", Intuition will automatically add the sign "[A] O" after the item's 
  5056. name:
  5057.  
  5058. PROJECT  Block  Windows  Search
  5059. |------------|
  5060. | Open [A] O |
  5061. | Save       |
  5062. | Save as    |
  5063. | Print      |
  5064. | Info       |
  5065. | Quit       |
  5066. |------------|
  5067.  
  5068. Your program will not notice any difference between a normal menu access, and a 
  5069. shortcut.
  5070.  
  5071. Remember to give enough space on the right side of the item box, so the Amiga 
  5072. character + sign will fit. If the item box was before 100 pixels wide you can 
  5073. set the width to 100 + COMMWIDTH, and everything will fit in nicely. (COMMWIDTH 
  5074. is a constant declared in the intuition.h file.) If the window is connected to 
  5075. a low-resolution screen, use the constant LOWCOMMWIDTH instead.
  5076.  
  5077. 7.4  MENU ITEMS
  5078.  
  5079. There exist two different types of menu items:
  5080. - Action items
  5081. - Attribute items
  5082.  
  5083. Action items can be selected over and over again, and every time they are 
  5084. selected they will send your program a message.
  5085.  
  5086. Attribute items on the other hand can only be selected once, and once they have 
  5087. been selected they need to be deselected before they can be selected again. The 
  5088. only way to deselect an Attribute item is to mutual exclude them (explained 
  5089. later in this chapter).
  5090.  
  5091. When an attribute item is selected Intuition will put a small checkmark, [v], 
  5092. before the item's name. If you want to use your own designed checkmark instead 
  5093. of the default one, you set the CheckMark pointer in your NewWindow structure 
  5094. to point to an Image structure which you have declared and initialized as 
  5095. desired.
  5096.  
  5097. If you use any attribute item in your menu you need to leave enough space at 
  5098. the left side of the box for the checkmark. If you use the default checkmark 
  5099. you can move the text in the menu CHECKWIDTH amount of pixels to the right. 
  5100. (CHECKWIDTH is a constant declared in the intuition.h file.) If the window is 
  5101. connected to a low-resolution screen (320 pixels wide), you should use the 
  5102. constant LOWCHECKWIDTH instead of CHECKWIDTH.
  5103.  
  5104. 7.5  MUTUAL EXCLUDE
  5105.  
  5106. This special and very useful function applies only on attribute items. The idea 
  5107. with mutual exclude is that when the user selects a certain item, some other 
  5108. attribute items are deselected automatically. For example, you are writing a 
  5109. wordprocessor and the user should be able to print the text as normal (plain) 
  5110. or with some special style (Bold, Underline or Italic). The user would then 
  5111. only be allowed to select Plain or one or more of the other styles (Bold and 
  5112. underlined for example). If the user selects Plain, all other styles should be 
  5113. deselected (mutual excluded). If the user on the other hand selects Bold, 
  5114. Underline or Italic the Plain item should be deselected.
  5115.  
  5116. Mutual exclude works like this:
  5117.  
  5118. 1. If the flag CHECKIT (see the MenuItem structure) is not set, the item is not 
  5119. an attribute item, it is an action item, and mutual exclude will have no effect 
  5120. on this item.
  5121.  
  5122. 2. If the flag CHECKIT is set, the item is an attribute item, and Intuition 
  5123. will make sure that the CHECKED flag is not set. If it is, Intuition will 
  5124. automatically remove it, and the item is unselected.
  5125.  
  5126. Every item has a MutualExclude field in which you can specify which items 
  5127. should be deselected when this item is activated. The first bit in the field 
  5128. refers to the first item in the item list, the second bit to the second item 
  5129. and so on.
  5130.  
  5131. In our previous example we would set the Plain item's MutualExclude field to 
  5132. 0xFFFFFFFE (0xFFFFFFFE is equal to 11111111111111111111111111111110). This 
  5133. would mutual exclude
  5134. all items except the first one. (Plain is the first item in the list, and 
  5135. should of course not be mutual excluded.)
  5136.  
  5137. The other items (Bold, Underline and Italic) should have their field set to 
  5138. 0x00000001 (0x00000001 is equal to 00000000000000000000000000000001). This 
  5139. would only mutual exclude the first item (the Plain item).
  5140.  
  5141. 7.6  OPEN A MENU
  5142.  
  5143. If you want to attach a menu strip to a window you need to:
  5144.  
  5145. 1. Declare and initialize one or more Menu structures. The Menu structures 
  5146. should be linked together, and each Menu structure has its own list of items. 
  5147. Each Menu structure represent one "menu heading"
  5148.  
  5149. 2. Declare and initialize one or more MenuItem structures which are connected 
  5150. to the Menu structures. Each MenuItem structure represent one item. You can 
  5151. connect a list of "subitems" to an Item structure if you want. (Subitems use 
  5152. the same data structure as normal items.)
  5153.  
  5154. 3. Call the function SetMenuStrip(). Important, before you close the window, or 
  5155. change the "menu strip" you must disconnect the menu from the window. You do it 
  5156. by calling the function ClearMenuStrip().
  5157.  
  5158. 7.6.1  INITIALIZE A MENU STRUCTURE
  5159.  
  5160. The Menu structure look like this:
  5161.  
  5162.  
  5163. struct Menu
  5164. {
  5165.   struct Menu *NextMenu;
  5166.   SHORT LeftEdge, TopEdge, Width, Height;
  5167.   USHORT Flags;
  5168.   BYTE *MenuName;
  5169.   struct MenuItem *FirstItem;
  5170.   SHORT JazzX, JazzY, BeatX, BeatY;
  5171. };
  5172.  
  5173. NextMenu:
  5174.     
  5175. Pointer to the next Menu structure in the menu strip list. The last Menu 
  5176. structure in the list must have the NextMenu set to NULL.
  5177.  
  5178. LeftEdge:
  5179.     
  5180. X position of the menu.
  5181.  
  5182. TopEdge:
  5183.     
  5184. Y position of the menu. For the moment this field is unused since all menus are 
  5185. positioned at the top of the display. Set it to 0.
  5186.  
  5187. Width:
  5188.     
  5189. The width of the menu.
  5190.  
  5191. Height:
  5192.     
  5193. The height of the menu. For the moment this field is unused since all menus are 
  5194. as high as the height of the title bar of the screen. Set it to 0.
  5195.  
  5196. Flags:
  5197.     
  5198. There exist only two different flags for the moment:
  5199.  
  5200.     
  5201. MENUENABLED: If this flag is set the menu is enabled, and the user can select 
  5202. items from it. If it is not set, the menu is ghosted and the user can not 
  5203. select any items from it.
  5204.                          
  5205.     
  5206. If you want the menu to be enabled when you submit it to Intuition you should 
  5207. set this flag. You can later change the status by calling the functions 
  5208. OnMenu() and OffMenu().
  5209.  
  5210.     
  5211. MIDRAWN:     This flag is set by Intuition when this menu is displayed to the 
  5212. user.
  5213.  
  5214. MenuName:
  5215.     
  5216. Pointer to a NULL-terminated string. The text will appear in the menu box at 
  5217. the top of the screen.
  5218.  
  5219. FirstItem:
  5220.     
  5221. Pointer to the first MenuItem in the item list.
  5222.  
  5223. These funny-named variables are for internal use only:
  5224.  
  5225. JazzX, JazzY, BeatX, BeatY:  Used by Intuition. Set to 0.
  5226.  
  5227. Here is an example of how to declare and initialize a Menu structure:
  5228.  
  5229. struct Menu my_menu=
  5230. {
  5231.   NULL,        /* NextMenu, no other menu structures   */
  5232.                /* connected.                           */
  5233.   0,           /* LeftEdge, 0 pixels to the right.     */
  5234.   0,           /* TopEdge, for the moment ignored by   */
  5235.                /* Intuition. Set to 0.                 */
  5236.   60,          /* Width, 60 pixels wide.               */
  5237.   0,           /* Height, for the moment ignored by    */
  5238.                /* Intuition. Set to 0.                 */
  5239.   MENUENABLED, /* Flags, this menu should be enabled.  */
  5240.   "Project",   /* MenuName, the title of the menu.     */
  5241.   &first_item, /* FirstItem, pointer to the first item */
  5242.                /* in the list.                         */
  5243.  
  5244.   0, 0, 0, 0   /* JazzX, JazzY, BeatX, BeatY           */
  5245. };
  5246.  
  5247. 7.6.2  INITIALIZE A MENUITEM STRUCTURE
  5248.  
  5249. The MenuItem structure look like this:
  5250.  
  5251. struct MenuItem
  5252. {
  5253.   struct MenuItem *NextItem;
  5254.   SHORT LeftEdge, TopEdge, Width, Height;
  5255.   USHORT Flags;
  5256.   LONG MutualExclude;
  5257.   APTR ItemFill;
  5258.   APTR SelectFill;
  5259.   BYTE Command;
  5260.   struct MenuItem *SubItem;
  5261.   USHORT NextSelect;
  5262. };
  5263.  
  5264. NextItem:
  5265.     
  5266. Pointer to the next MenuItem structure in the item list. The last item should 
  5267. have its NextItem field set to NULL.
  5268.  
  5269. LeftEdge:
  5270.     
  5271. X position of the item's select box relative to the LeftEdge of the Menu 
  5272. structure.
  5273.  
  5274. TopEdge:
  5275.     
  5276. Y position of the item's select box relative to the topmost position allowed by 
  5277. intuition. The topmost position is automatically calculated by Intuition which 
  5278. examines the font size, how many items above etc. Set TopEdge to 0 in order to 
  5279. select the topmost position.
  5280.  
  5281. Width:
  5282.     
  5283. The width of the item's select box.
  5284.  
  5285. Height:
  5286.     
  5287. The height of the item's select box.
  5288.  
  5289. Flags:
  5290.     
  5291. Here are the flags you and Intuition can use:
  5292.  
  5293.     
  5294. CHECKIT:     Set this flag if you want the item to be an attribute item, else 
  5295. it will be an action item. If you set this flag Intuition will put the small 
  5296. checkmark in front of the itmetext when this item is selected, so make sure 
  5297. there is enough space for it.
  5298.  
  5299.     
  5300. CHECKED:     If the item is an attribute item (the CHECKIT flag is set), this 
  5301. flag is set by Intuition when the item is selected by the user. The flag is 
  5302. also automatically removed by Intuition when this item is mutual excluded.
  5303.  
  5304.     
  5305. You can set this flag yourself before you submit the menu strip to Intuition, 
  5306. if you want the item to be initially selected. 
  5307.  
  5308.     
  5309. HIGHITEM:    The item will be highlighted, and this flag set, when the user 
  5310. moves the pointer over the item's select box.
  5311.                             
  5312.     
  5313. You need to set one of the following four flags which will tell Intuition what 
  5314. kind of highlighting you want:
  5315.  
  5316.     
  5317. HIGHCOMP:  Complement the colours of all the pixels in the item's select box.
  5318.  
  5319.     
  5320. HIGHBOX:   Draw a box around the item's select box.
  5321.  
  5322.     
  5323. HIGHIMAGE: Display an alternative Image or Text.
  5324.                                        
  5325.     
  5326. HIGHNONE:  No highlighting.
  5327.  
  5328.     
  5329. ITEMENABLED: If this flag is set the item is enabled, and the user can select 
  5330. it. If this flag is not set, the item is ghosted and the user can not select 
  5331. it.
  5332.                          
  5333.     
  5334. If you want the item to be enabled when you submit it to Intuition you should 
  5335. set this flag. You can later change the status by calling the functions 
  5336. OnMenu() and OffMenu().
  5337.  
  5338.     
  5339. ITEMTEXT:    If the item is rendered with text you should set this flag. 
  5340. Intuition will then expect ItemFill and SelectFill to point to IntuiText 
  5341. structures. If this flag is not set the item will be rendered with an image, 
  5342. and Intuition will expect ItemFill and SelectFill to point to Image structures.
  5343.  
  5344.     
  5345. COMMSEQ:     If the item also should be accessible from the keyboard you need 
  5346. to set this flag. Remember to tell Intuition which key should be pressed 
  5347. together with the "Amiga key" in order to select the item. You do it by giving 
  5348. the variable Command the desired character.
  5349.  
  5350.     
  5351. ISDRAWN:     This flag is set by Intuition when this item's subitems are 
  5352. displayed, and cleared when not.
  5353.  
  5354. MutualExclude:
  5355.     
  5356. This variable will tell Intuition which attribute items should be mutual 
  5357. excluded (deselected when this item is selected). The first bit refers to the 
  5358. first item in the active list (item list or subitem list), the second bit 
  5359. refers to the second item and so on. For example:
  5360.                
  5361.     
  5362. The number 0x0000000B (hexadecimal) is equal to 
  5363. 00000000000000000000000000001011 (binary), and Intuition would therefore try to 
  5364. mutual exclude the first, the second and the fourth item.
  5365.  
  5366. ItemFill:
  5367.     
  5368. Pointer to an Image structure (the ITEMTEXT flag not set) or to an IntuiText 
  5369. structure (the ITEMTEXT flag set), which will be used by Intuition to render 
  5370. this item.
  5371.  
  5372. SelectFill:
  5373.     
  5374. Pointer to an Image structure (the ITEMTEXT flag not set) or to an IntuiText 
  5375. structure (the ITEMTEXT flag set), which will render this item when it is 
  5376. highlighted. (This field is only used if the flag HIGHIMAGE is set.)
  5377.  
  5378. Command:
  5379.     
  5380.  If the user should be able to access this item from the keyboard, you need to 
  5381. tell Intuition which key should be used. This field should therefore contain 
  5382. the desired character. (Remember to set the flag COMMSEQ in the Flags field.)
  5383.  
  5384. SubItem:
  5385.     
  5386. Pointer to a subitem list if there exist on, else NULL. If this item is already 
  5387. a subitem, this field is ignored by Intuition. (Remember, the subitem list 
  5388. consists of a linked list of MenuItem structures.)
  5389.  
  5390. NextSelect:
  5391.     
  5392. This field is set by Intuition and will contain a special number if more items 
  5393. after this one was selected at the same menu event, else it will contain 
  5394. MENUNULL. (This will be discussed later in the chapter.) Set it to MENUNULL.
  5395.  
  5396. Here is an example of how to declare and initialize a MenuItem structure:
  5397.  
  5398. struct MenuItem my_first_item=
  5399. {
  5400.   &my_second_item,   /* NextItem, pointer to the next item   */
  5401.                      /* in the list.                         */
  5402.   0,                 /* LeftEdge, 0 pixels to right.         */
  5403.   0,                 /* TopEdge, the topmost position.       */
  5404.   150,               /* Width, 150 pixels wide.              */
  5405.   10,                /* Height, 10 lines high.               */
  5406.   CHECKIT|           /* Flags, an attribute item.            */
  5407.   CHECKED|           /*        should initially be selected. */
  5408.   COMMSEQ|           /*        accessible from the keyboard. */
  5409.   HIGHCOMP|          /*        complement the colours when   */
  5410.   ITEMENABLED,       /*        highlighted. The item should  */
  5411.                      /*        be enabled. Not ghosted.      */
  5412.   0x00000037,        /* MutualExclude, deselect if possible  */
  5413.                      /* item: 1, 2, 3, 5 and 6.              */
  5414.   &my_image          /* ItemFill, pointer to an Image        */
  5415.                      /* structure used to render the item.   */
  5416.                      /* Since the flag ITEMTEXT was not set, */
  5417.                      /* Intuition will assume that this is a */
  5418.                      /* pointer to an Image structure, and   */
  5419.                      /* not a pointer to an IntuiText        */
  5420.                      /* structure.                           */
  5421.   NULL,              /* SelectFill, NULL since we complement */
  5422.                      /* the colours instead of displaying an */
  5423.                      /* alternative image.                   */
  5424.   'O',               /* Command, the character which should  */
  5425.                      /* be pressed together with the "Amiga  */
  5426.                      /* key" in order to execute the         */
  5427.                      /* shortcut.                            */
  5428.   NULL,              /* SubItem, this item has no subitems   */
  5429.                      /* connected to it.                     */
  5430.   MENUNULL           /* NextSelect, set later by Intuition.  */
  5431. };
  5432.  
  5433. 7.6.3  HOW TO SUBMIT AND REMOVE A MENU STRIP TO/FROM A WINDOW
  5434.  
  5435. Once you have declared and initialized the necessary Menu and MenuItem 
  5436. structures and linked them together you only need to call the function 
  5437. SetMenuStrip(), and the menu strip is connected to your window. Remember that 
  5438. you need to first open the window, before you can submit a menu strip to the 
  5439. window.
  5440. If you have a pointer to an already opened window, my_window, and a pointer to 
  5441. the first Menu structure in your list, my_first_menu, you attach the menu strip 
  5442. like this:
  5443.  
  5444. SetMenuStrip( my_window, my_first_menu );
  5445.  
  5446. If you want to change a menu strip which is already attached to a window you 
  5447. first need to remove it. You do it by calling the function ClearMenuStrip(). 
  5448. You can then change what ever you want to change, and attach it once again.
  5449.  
  5450. To remove a menu strip from a window, you only need a pointer to that window, 
  5451. eg my_window, and then call the function ClearMenuStrip() like this:
  5452.  
  5453. ClearMenuStrip( my_window );
  5454.  
  5455. If a menu strip is connected to a window, and you want to close that window, 
  5456. you should first remove the menu. If your program does not remove the menu 
  5457. strip before it closes the window, there is a risk that the user has activated 
  5458. the menu, and you would end up with a nice system crash. So, to be on the safe 
  5459. side, always call the function ClearMenuStrip() before you close a window which 
  5460. has a menu strip connected to it.
  5461.  
  5462. 7.7  SPECIAL IDCMP FLAGS
  5463.  
  5464. There exist two special IDCMP flags which are close related to menus. They are 
  5465. MENUPICK and MENUVERIFY. The IDCMP flag MENUPICK tells your program that the 
  5466. user has picked zero or more items from a menu. MENUVERIFY allows your program 
  5467. to finish off something before the menu is displayed, and you can even abort 
  5468. the whole menu operation if you want.
  5469.  
  5470. 7.7.1  MENUPICK
  5471.  
  5472. If you want your program to receive a message every time the user has picked 
  5473. zero or more items/ subitems from the menu, you need to set the flag MENUPICK 
  5474. in the IDCMPFlags field in your NewWindow structure. You can then handle this 
  5475. message as normal IDCMP messages. (See chapter 8 IDCMP for more information 
  5476. about IDCMP messages.)
  5477.  
  5478. Once you receive a MENUPICK message you need to check if any items were 
  5479. selected. The Code field of the IntuiMessage structure will contain a special 
  5480. code number ("Menu Number") which we can examine in order to see which item was 
  5481. selected. The menu number is equal to MENUNULL if no item was selected. Use the 
  5482. function ItemAddress() with a pointer to the menu strip and the menu number as 
  5483. parameters, and it will return the address of the selected item.
  5484.  
  5485. The problem which will arise is that the user can select several items during 
  5486. one single menu operation, and your program needs to check them all. There is 
  5487. however an easy solution for this problem. If an item was selected, we can 
  5488. examine the NextSelect field of that item's structure, and that number is 
  5489. either MENUNULL (no more items selected), or another special menu number. (If 
  5490. it was not equal to MENUNULL you should again call the function ItemAddress() 
  5491. so you get a pointer to the second item's structure, and you should then 
  5492. examine the NextSelect field of that structure and so on...).
  5493.  
  5494. Here is a fragment of a program which handles MENUPICK event:
  5495.  
  5496. if( class == MENUPICK )
  5497. {
  5498.   /* The user has released the right mouse button. */
  5499.   
  5500.   /* The variable menu_number is initialized with the code */
  5501.   /* value:                                                */
  5502.   menu_number = code;
  5503.   
  5504.   /* As long as menu_number is not equal to MENUNULL we */
  5505.   /* stay in the while loop: */
  5506.   while( menu_number != MENUNULL )
  5507.   {
  5508.     /* Get the address of the item: */
  5509.     item_address = ItemAddress( &first_menu, menu_number );
  5510.   
  5511.     /* Process this item... */
  5512.     
  5513.     /* Get the following item's menu number: */
  5514.     menu_number = item_address->NextSelect;
  5515.   }
  5516.   
  5517.   /* All items which were selected has been processed! */
  5518. }
  5519.  
  5520. If you have a menu number you can use Intuitions three macros to check which 
  5521. menu/item/subitem was selected. They all return 0, if it was the first 
  5522. menu/item/subitem in the list, 1 if it was the second and so on.
  5523.  
  5524. MENUNUM( menu_number );
  5525.     
  5526. Is equal to 0 if the item was selected from the first menu, 1 if it was from 
  5527. the second and so on. It is equal to NOMENU if the user did not select any item 
  5528. from the menus.
  5529.  
  5530. ITEMNUM( menu_number );
  5531.     
  5532. Is equal to 0 if the firs item was selected in this item list, 1 if it was the 
  5533. second and so on. It is equal to NOITEM if the user did not select any item.
  5534.  
  5535. SUBNUM( menu_number );
  5536.     
  5537. Is equal to 0 if it the firs subitem was selected in this subitem list, 1 if it 
  5538. was the second and so on. It is equal to NOSUB if the user did not select any 
  5539. subitem.
  5540.  
  5541. 7.7.2  MENUVERIFY
  5542.  
  5543. The MENUVERIFY message tells your program that the user has pressed the right 
  5544. mouse button, and a menu will be activated. However, the menu strip will first 
  5545. be activated when you program has replied, and you can therefore, thanks to 
  5546. this warning, wait with the menu event for a while, or even stop it totally, if 
  5547. necessary.
  5548.  
  5549. If you want your program to receive a message every time the a menu will be 
  5550. activated you need to set the flag MENUVERIFY in the IDCMPFlags field in your 
  5551. NewWindow structure. The MENUVERIFY flag acts like the REQVERIFY flag for 
  5552. requesters.
  5553.  
  5554. Here is an example on how your program should handle this verification message, 
  5555. and how you can cancel a menu operation:
  5556.  
  5557. /* Wait until we receive one or more messages: */
  5558. Wait( 1 << my_window->UserPort->mp_SigBit );
  5559.  
  5560. /* As long as we can collect messages successfully, we will */
  5561. /* stay in this while loop:                                */
  5562. while(my_message = GetMsg( my_window->UserPort ));
  5563. {
  5564.   /* After we have collected the message we can read it,  */
  5565.   /* and save any important values which we maybe want to */
  5566.   /* check later:                                         */
  5567.   class = my_message->Class;
  5568.   code = my_message->Code;
  5569.  
  5570.  
  5571.   /* Before we reply we need to see if we have received a */
  5572.   /* MENUVERIFY message:                                  */
  5573.   
  5574.   if( class == MENUVERIFY )
  5575.   {
  5576.     /* Yes, we have received a MENUVERIFY message!          */
  5577.     /* The user wants to activate a menu, but the problem   */
  5578.     /* is that we do not know if it is our window's menu    */
  5579.     /* that will be activated, or some other window's menu. */
  5580.     /* We can however check it by examining the Code field  */
  5581.     /* of the message. If it is equal to MENUWAITING, it    */
  5582.     /* means that it is not your window's menu that will be */
  5583.     /* activated, but if Code is equal to MENUHOT it means  */
  5584.     /* it is is your window's menu that will be activated!  */
  5585.     
  5586.     if( code == MENUWAITING )
  5587.     {
  5588.       /* It is not your window's menu that will be activated! */
  5589.       
  5590.       /* Your program can take a pause if necessary. You  */
  5591.       /* maybe want to finish of with some drawings, so   */
  5592.       /* your program does not trash any menus. This is   */
  5593.       /* especially important if you are using the low-   */
  5594.       /* level graphics routines since they do not bother */
  5595.       /* about, menus etc, and will draw over and destroy */
  5596.       /* anything in their way.                           */
  5597.       
  5598.       /* Once the program is ready it should reply the */
  5599.       /* message, and the menu will be activated. */
  5600.     }
  5601.     else
  5602.       if( code == MENUHOT )
  5603.       {
  5604.         /* It is your window's menu that will be activated!  */
  5605.         
  5606.         /* You can now take a pause and finish of with       */
  5607.         /* something before you let Intuition activate the   */
  5608.         /* menu, or you can even stop the whole menu         */
  5609.         /* operation if necessary. If you are writing a      */
  5610.         /* paint program you maybe only want the user to be  */
  5611.         /* able to activate the menu if the pointer is at    */
  5612.         /* the top of the display. That would mean that the  */
  5613.         /* user can draw with the right mouse button, and    */
  5614.         /* when the user wants to make a menu choice, he/    */
  5615.         /* she simply moves the pointer to the top of the    */
  5616.         /* display, and then presses the right mouse button. */
  5617.         
  5618.         /* We will now check if the pointer is somewhere at  */
  5619.         /* the top of the display:                           */
  5620.         if( my_window->MouseY < 10)
  5621.         {
  5622.           /* The Y coordinate of the pointer is at least */
  5623.           /* less than 10 lines below the TopEdge of the */
  5624.           /* window.                                     */
  5625.         
  5626.           /* The menu operation should continue as soon  */
  5627.           /* as possible!                                */
  5628.         }
  5629.         else
  5630.         {
  5631.           /* The pointer is below the Title bar of the */
  5632.           /* window! Cancel the whole menu operation!  */
  5633.           
  5634.           /* To cancel a menu operation you need to change   */
  5635.           /* the Code field to MENUCANCEL. IMPORTANT! Do not */
  5636.           /* change the code variable since it is just a     */
  5637.           /* copy of the real Code value. What we need to do */
  5638.           /* is to change the real value, and that is still  */
  5639.           /* OK since we have not replied yet.               */
  5640.  
  5641.           my_message->Code=MENUCANCEL;
  5642.         }
  5643.       }
  5644.   }
  5645.  
  5646.   /* After we have read the message we reply as fast as    */
  5647.   /* possible: REMEMBER! Do never try to read or change a  */
  5648.   /* message after you have replied! Some other process is */
  5649.   /* maybe using it.                                       */
  5650.   ReplyMsg( my_message );
  5651.  
  5652.  
  5653. If you set the RMBTRAP flag in your NewWindow's Flags field you tell Intuition 
  5654. that you do not want to use any menus at all for this window. Your program 
  5655. could then use the right mouse button for something else. (See chapter 8 IDCMP 
  5656. for more information about RMBTRAP.)
  5657.  
  5658. 7.8  MENU NUMBERS
  5659.  
  5660. Here is a description of how the "menu numbers" actually work. (This can change 
  5661. later so do not calculate anything yourself, let Intuition's macros do it 
  5662. instead.)
  5663.  
  5664. The menu number is a 16-bit variable, where the first five bits are used for 
  5665. the menus, the following six bits are used for the items, and the last five 
  5666. bits are used for the subitems:
  5667.  
  5668.  
  5669. c c c c c b b b b b b a a a a a
  5670. |         |           |
  5671. |         |           > Menu
  5672. |         > Item
  5673. > SubItem
  5674.  
  5675. This means the Intuition can "only" handle up to 31 Menus, each with up to 63 
  5676. Items, where each item can have up to 31 SubItems. I do not think this will be 
  5677. any restrictions for your program.
  5678.  
  5679. If a field is equal to 0 it means the first menu/item/subitem, if it is equal 
  5680. to 1 it means the second and so on. If all bits are on it means that no 
  5681. menu/item/subitem was selected. See following example:
  5682.  
  5683. The menu number 0xF803 means:
  5684.  
  5685. No SubItem, the first item, from the fourth menu.
  5686. 0xF803 (h) = 1111 1000 0000 0011 (b)
  5687.  
  5688. Menu number  11111 000000 00011  (b)
  5689.              |     |      |
  5690.              |     |      >  00011 =  3 = fourth Menu
  5691.              |     >        000000 =  0 = first Item
  5692.              >               11111 = 31 = NOSUB
  5693.  
  5694. To calculate this you should use Intuition's macros:
  5695.  
  5696. MENUNUM( 0xF803 ) == 3  the fourth menu.
  5697. ITEMNUM( 0xF803 ) == 0  the first item.
  5698. SUBNUM( 0xF803 )  == 31 (NOSUB).
  5699.  
  5700. It sometimes happens that you want to go the other way, and calculate your own 
  5701. menu number. You should then use the macros SHIFTMENU, SHIFTITEM and SHIFTSUB 
  5702. which does the opposite of MENUNUM etc. If you are going to use the functions 
  5703. OnMenu() and OffMenu() (explained later), you need to send a menu number as one 
  5704. of the parameters. If you for example want to "ghost" the second item in the 
  5705. third menu, you calculate the menu number like this:
  5706.  
  5707. menu_number = SHIFTMENU(2) + SHIFTITEM(1) + SHIFTSUB(NOSUB);
  5708.               [third menu]   [second item]  [no subitem]
  5709.  
  5710. 7.9  FUNCTIONS
  5711.  
  5712. Here are some commonly used function which affects menus:
  5713.  
  5714. SetMenuStrip()
  5715.  
  5716. This function connects a menu strip to a window. Remember that the window must 
  5717. have been opened before you may connect a menu strip to that window.
  5718.  
  5719. Synopsis:
  5720.     
  5721. SetMenuStrip( my_window, my_menu );
  5722.  
  5723.  my_window:
  5724.     
  5725. (struct Window *) Pointer to the window which the menu strip should be 
  5726. connected to.
  5727.  
  5728. my_menu:
  5729.     
  5730. (struct Menu *) Pointer to the first Menu structure in the menu strip.
  5731. ClearMenuStrip()
  5732.  
  5733. This function removes a menu strip from a window. Remember to always remove the 
  5734. menu strip before you close the window, or changes the menu strip.
  5735.  
  5736. Synopsis:
  5737.     
  5738. ClearMenuStrip( my_window );
  5739.  
  5740. my_window:
  5741.     
  5742. (struct Window *) Pointer to the window which menu strip should be removed.
  5743.  
  5744. ItemAddress()
  5745.  
  5746. This function returns a pointer to the Menu or Item structure which is 
  5747. specified by the menu number.
  5748.   
  5749. Synopsis:
  5750.     
  5751. ItemAddress( my_menu, menu_number );
  5752.   
  5753. my_menu:
  5754.     
  5755. (struct Menu *) Pointer to the first Menu structure in the menu strip.
  5756.  
  5757. menu_number:
  5758.     
  5759. (USHORT) This menu number specifies a subitem/item/menu.
  5760.  
  5761. OffMenu()
  5762.  
  5763. This function can disable a subitem, an item or even a whole menu. The image or 
  5764. text of the disabled items etc will be "ghosted", and the user can not select 
  5765. them.
  5766.   
  5767. Synopsis:
  5768.     
  5769. OffMenu( my_window, menu_number );
  5770.  
  5771. my_window:
  5772.     
  5773. (struct Window *) Pointer to the window which the menu strip is connected to.
  5774.   
  5775. menu_number:
  5776.     
  5777. (USHORT) This menu number specifies what should be disabled. Use the macros 
  5778. SHIFTMENU, SHIFTITEM and SHIFTSUB to calculate the correct menu number. If you 
  5779. just specify a menu, all items to that menu will be disabled. If you specify a 
  5780. menu and an item, that item will be disabled, and so all subitems connected to 
  5781. it if there are any.
  5782.  
  5783. OnMenu()
  5784.  
  5785. This function can enable a subitem, an item or even a whole menu. The image or 
  5786. text of the enabled items etc, will become normal (not "ghosted") and the user 
  5787. can now select them.
  5788.   
  5789. Synopsis:
  5790.     
  5791. OnMenu( my_window, menu_number );
  5792.  
  5793. my_window:
  5794.     
  5795. (struct Window *) Pointer to the window which the menu strip is connected to.
  5796.   
  5797. menu_number:
  5798.     
  5799. (USHORT) This menu number specifies what should be enabled. Use the macros 
  5800. SHIFTMENU, SHIFTITEM and SHIFTSUB to calculate the correct menu number. If you 
  5801. just specify a menu, all items to that menu will be enabled. If you specify a 
  5802. menu and an item, that item will be enabled, so all subitem connected to it if 
  5803. there are any.
  5804.  
  5805. 7.10  MACROS
  5806.  
  5807. Here are some commonly used macros:
  5808.  
  5809. These three macros takes a "menu number" as the only parameter, and examines 
  5810. it. These are very handy if you have received a menu number, and you want to 
  5811. check which menu and which item was selected etc:
  5812.  
  5813. MENUNUM( menu_number );
  5814. Is equal to 0 if the menu number specifies the first menu, 1 if it specifies 
  5815. the second, and so on. It is equal to NOMENU if it does not specify any menus 
  5816. at all.
  5817.  
  5818. ITEMNUM( menu_number );
  5819. Is equal to 0 if the menu number specifies the first item, 1 if it specifies 
  5820. the second, and so on. It is equal to NOITEM if it does not specify any items 
  5821. at all.
  5822.  
  5823. SUBNUM( menu_number );
  5824. Is equal to 0 if the menu number specifies the first subitem, 1 if it specifies 
  5825. the second, and so on. It is equal to NOSUB if it does not specify any subitems 
  5826. at all.
  5827.  
  5828. These three macros does the opposite of the first three. With help of these 
  5829. macros you can make your own menu number just by specifying which menu, item 
  5830. and subitem you want.
  5831.  
  5832. SHIFTMENU( menu );
  5833. Is equal to a menu number which specifies this menu. ("menu" is a value between 
  5834. 0 and 30, or NOMENU if no menu should be specified.)
  5835.  
  5836. SHIFTITEM( item );
  5837. Is equal to a menu number which specifies this item. ("item" is a value between 
  5838. 0 and 62, or NOITEM if no item should be specified.)
  5839.  
  5840. SHIFTSUB( sub );
  5841. Is equal to a menu number which specifies this subitem. ("sub" is a value 
  5842. between 0 and 30, or NOSUB if no subitem should be specified.)
  5843.  
  5844. 7.11  EXAMPLES
  5845.  
  5846. Example 1
  5847. This program opens a normal window to which we connect a menu strip. The menu 
  5848. consists of four items: Plain, Bold, Underlined and Italic. The user can select 
  5849. either Plain or a combination of the other styles. (If the user selects Plain 
  5850. all other modes will be mutual excluded, but if the user on the other hand 
  5851. selects Bold, Underlined or Italic, only the Plain option will be mutual 
  5852. excluded.
  5853.   
  5854. This example also shows how a program should handle the IDCMP flags, and how to 
  5855. collect several messages from one single menu event.
  5856.  
  5857. Example 2
  5858. This example is very similar to Example 1, but we have this time put the edit 
  5859. styles in a subitem box which is connected to the one and only item box called 
  5860. "Style".
  5861.  
  5862. Example 3
  5863. This example is very similar to Example 2, but the user can this time also 
  5864. access the subitems from the keyboard. For example, to select Bold the user 
  5865. only needs to press the right Amiga key [A] together with the "B" key.
  5866.  
  5867. Example 4
  5868. This program opens a normal window to which we connect a menu strip. The menu 
  5869. consists of two items: Readmode and Editmode. The readmode item is selected and 
  5870. ghosted, and when the user selects the editmode item, it will become disabled 
  5871. (ghosted) while the readmode item will be enabled (not ghosted). This means 
  5872. that if the program is in "readmode", the user should only be able to chose the 
  5873. "editmode", and v.v. The purpose with this program is to show how you can use 
  5874. the OnMenu and OffMenu functions in order to make an "user-friendly interface".
  5875.  
  5876. Example 5
  5877. Exactly as Example 1 except that we have changed Intuition's checkmark to our 
  5878. own customized "arrow".
  5879.  
  5880. Example 6
  5881. This program opens a normal window to which we connect a menu strip. The menu 
  5882. consists of six small dices which are all action items. This example shows how 
  5883. you can use Images inside a menu.
  5884.  
  5885. Example 7
  5886. This program opens a normal window to which we connect a menu strip. The menu 
  5887. consists of one small action item with two images.
  5888.  
  5889. Example 8
  5890. Same as Example 1 except that we this time will verify any menu operations. If 
  5891. the user tries to activate this program's menu we check if the position of the 
  5892. pointer is somewhere at the top of the window (less than 10 lines down). In 
  5893. that case the menu operation will continue as normal, otherwise we cancel the 
  5894. menu operation.
  5895.  
  5896.  
  5897. IDCMP
  5898.  
  5899. 8.1  INTRODUCTION
  5900.  
  5901. We have in the last four chapters talked about IDCMP, but have never actually 
  5902. explained what it is. But in this chapter we will at last satisfy your hunger 
  5903. for more information. IDCMP stands for Intuition's Direct Communications 
  5904. Messages Ports (nice), and is the most commonly used way of receiving messages 
  5905. from Intuition, and the only way to communicate to Intuition.
  5906.  
  5907. 8.2  IDCMP PORTS
  5908.  
  5909. When something happens inside the Amiga, a disk is inserted, a gadget is 
  5910. selected etc, a message is automatically created. Intuition will then examine 
  5911. the messages and check if your program is interested to hear about it. (Every 
  5912. window has a list of none or more IDCMP flags which tells Intuition what this 
  5913. window is interested of.) If a program is interested of the message, that 
  5914. program will receive a special message (IntuiMessage), which contains 
  5915. interesting information about the message.
  5916.  
  5917. ---------------------------   Messages created inside the Amiga.
  5918. | DISKINSERTED   MENUPICK |   For example, a disk is inserted,
  5919. |    CLOSEWINDOW          |   a menu is activated, a window is
  5920. |  NEWSIZE    GADGETDOWN  |   closed etc...
  5921. ---------------------------
  5922.     |   |   |   |   |
  5923.     V   V   V   V   V
  5924.       -------------           Intuition examines every message
  5925.       | INTUITION |           and checks if any program is
  5926.       -------------           interested of it.
  5927.      /            \
  5928. DISKINSERTED   GADGETDOWN     If program A is interested of
  5929.     |              |          DISKINSERTED messages, Intuition
  5930.     V              V          will pass that one along to
  5931. ------------- -------------   program A. If program B is 
  5932. | PROGRAM A | | PROGRAM B |   interested in GADGETDOWN messages
  5933. ------------- -------------   program B will receive a message
  5934.                               every time a gadget is selected
  5935.                               in program B's window.
  5936.  
  5937.                               All other messages which no
  5938.                               program were interested in will
  5939.                               be thrown away.
  5940.  
  5941. Intuition will always start to examine the active window first, and many IDCMP 
  5942. messages will probably be "swallowed". If program B is active, and Intuition 
  5943. has found a GADGETDOWN message, that message would be passed to program B, and 
  5944. all other programs would never hear about it.
  5945.  
  5946. Some messages are important for all programs, such as DISKINSERTED, and will be 
  5947. passed to ALL "interested" windows. (If a window has its IDCMPFlags field set 
  5948. to DISKINSERTED, that window is interested about disk inserted messages.)
  5949.  
  5950. 8.3  HOW TO RECEIVE IDCMP MESSAGES
  5951.  
  5952. If you want to receive messages from Intuition you need to:
  5953. 1. Open an IDCMP port.
  5954. 2. Wait for messages.
  5955. 3. Collect the messages.
  5956. 4. Examine them.
  5957. 5. Reply. (Tell Intuition that you have read the message)
  5958.  
  5959. 8.3.1  OPEN IDCMP PORTS
  5960.  
  5961. The IDCMP port can be automatically allocated by Intuition when you open a 
  5962. window. You only need to specify in the NewWindow structure's IDCMPFlags field 
  5963. which messages you want to receive from Intuition, and the rest is done for 
  5964. you. For example, if you open a window with the IDCMPFlags field set to 
  5965. GADGETDOWN, a port would be allocated for you, and your program would receive a 
  5966. message every time a gadget has been selected.
  5967.  
  5968. If you already have opened a window you can later change the IDCMP ports by 
  5969. calling the function ModifyIDCMP().
  5970.  
  5971. 8.3.2  WAIT FOR MESSAGES
  5972.  
  5973. Once an IDCMP port has been opened your program only need to wait until one or 
  5974. more messages arrives. There are two different ways of waiting for messages:
  5975.  
  5976. 1. The Passive Way.
  5977.     
  5978. Your program is halted and will only wake up when a message arrives. This will 
  5979. increase the speed of other applications since the CPU does not need to bother 
  5980. about your program as long as it is sleeping. Use the function Wait().
  5981.  
  5982. 2. The Active Way.
  5983.     
  5984. Your program tries to collect a message, and if it could not find any message 
  5985. it tries again. This is necessary if you want your program to continue doing 
  5986. something, and not stop waiting for a message to arrive.
  5987.  
  5988. 8.3.3  COLLECT MESSAGES
  5989.  
  5990. When you collect a message you should use the function GetMsg(). It will return 
  5991. a pointer to an IntuiMessage structure, which contains all important 
  5992. information about the message, or NULL if it could not collect any message.
  5993.  
  5994. 8.3.4  EXAMINE THE MESSAGE
  5995.  
  5996. Once you have collected a message successfully you can examine the IntuiMessage 
  5997. structure. The IntuiMessag structure look like this:
  5998.  
  5999. struct IntuiMessage
  6000. {
  6001.   struct Message ExecMessage;
  6002.   ULONG Class;
  6003.   USHORT Code;
  6004.   USHORT Qualifier;
  6005.   APTR IAddress;
  6006.   SHORT MouseX, MouseY;
  6007.   ULONG Seconds, Micros;
  6008.   struct Window *IDCMPWindow;
  6009.   struct IntuiMessage *SpecialLink;
  6010. };
  6011. ExecMessage:
  6012.     
  6013. Used by the Exec so do not touch it.
  6014.  
  6015. Class:
  6016.     
  6017. Contains the IDCMP flag.
  6018.  
  6019. Code:
  6020.     
  6021. Contains some special values which is closely related to the IDCMP flag 
  6022. (Class). For example, if you receive a MENUVERIFY message you can examine the 
  6023. Code field to see if it is your program's Menu (Code == MENUHOT) or some other 
  6024. program's Menu (Code == MENUWAITING) that will be displayed. If you on the 
  6025. other hand receives RAWKEY or VANILLAKEY messages the Code field will contain 
  6026. the key code and so on.
  6027.  
  6028. Qualifier:
  6029.     
  6030. If your program receives RAWKEY messages (untranslated keycodes), this field 
  6031. contains information like if the SHIFT or CTRL key was pressed or not. (A copy 
  6032. of the ie_Qualifier.)
  6033.  
  6034. MouseX:
  6035.     
  6036. X position of the pointer relative to the top left corner of your window.
  6037.  
  6038. MouseY:
  6039.     
  6040. Y position of the pointer relative to the top left corner of your window.
  6041.  
  6042. Seconds:
  6043.     
  6044. Copy of the system clock's seconds.
  6045.  
  6046. Micros:
  6047.     
  6048. Copy of the system clock's microseconds.
  6049.  
  6050. IAddress:
  6051.     
  6052. Pointer to that object that created the message. For example, if you receive a 
  6053. GADGETDOWN message, this field contains a pointer to the Gadget that was 
  6054. selected.
  6055.  
  6056. IDCMPWindow:
  6057.     
  6058. Pointer back to the window that sent this message.
  6059.  
  6060. SpecialLink:
  6061.     
  6062. Used by Exec and Intuition so do not touch it.
  6063.  
  6064. The best way to examine this structure is to copy all important values and then 
  6065. reply as fast as possible. (Intuition will be slowed down if you do not reply 
  6066. fast.) You can then (after you have replied) check the copied values. 
  6067. (Remember! Do not use the IntuiMessage structure any more once you have 
  6068. replied.)
  6069.  
  6070. 8.3.5  REPLY
  6071.  
  6072. Once your program has read everything it is interested of it should reply back 
  6073. to Intuition by calling the function ReplyMsg(). This tells Intuition that you 
  6074. have finished with reading the message.
  6075.  
  6076. Important! Once you have replied you may NOT examine/change the IntuiMessage 
  6077. structure any more. Some other program or Intuition may use it!
  6078.  
  6079. 8.3.6  EXAMPLE
  6080.  
  6081. Here is an example of how your program should collect and process IDCMP 
  6082. messages: (This is the Passive Way of collecting messages.)
  6083.  
  6084. /* 1. Wait until a message arrive: */
  6085. Wait( 1 << my_window->UserPort->mp_SigBit );
  6086.  
  6087. /* (my_window is a pointer to a window.)     */
  6088. /* (Do not bother to much about the funny formula.) */ 
  6089.  
  6090. /* 2. Try to collect a message: */
  6091. my_message = GetMsg( my_window->UserPort );
  6092.  
  6093.  
  6094. /* Could we collect a message? (If message == NULL we have */
  6095. /* not collected any message.                              */
  6096. if( my_message )
  6097. {
  6098.   /* YES! We have collected a message successfully. */
  6099.  
  6100.  
  6101.   /* 3. We should now examine the IntuiMessage structure, */
  6102.   /*    and save any important values. (If we save the    */
  6103.   /*    information we can reply as soon as possible, and */
  6104.   /*    later examine the values.)                        */
  6105.   class   = my_message->Class;
  6106.   code    = my_message->Code;
  6107.   address = my_message->IAddress;
  6108.   
  6109.  
  6110.   /* 4. We should now reply since we have finished reading */
  6111.   /*    the IntuiMessage structure. (Your program should   */
  6112.   /*    always reply as fast as possible.)                 */
  6113.   ReplyMsg( my_message );
  6114.   
  6115.   
  6116.   /* 5. We can now examine what the message actually was */
  6117.   /*    about: (We have replied so we may NOT examine    */
  6118.   /*    the IntuiMessage structure any more, but we may  */
  6119.   /*    of course check the variables: class, code and   */
  6120.   /*    address.)                                        */
  6121.   switch( class )
  6122.   {
  6123.     case GADGETDOWN: /* A gadget has been pressed.       */
  6124.     case GADGETUP:   /* A gadget has been released.      */
  6125.     case MENUPICK:   /* A menu item has been selected... */
  6126.     /* And so on...                                      */
  6127.   }
  6128. }
  6129.  
  6130. This example is very fine, but what happens if two messages arrives at the same 
  6131. time? Well, the first message would be dealt with as normal, but the second 
  6132. message would never be processed. After we have waited for a message we should 
  6133. actually be prepared to process many messages. We should therefore use a 
  6134. while-loop, and stay in the loop as long as we can collect messages 
  6135. successfully. Once we could not collect any more we should put our task to 
  6136. sleep again.
  6137.  
  6138. Here is a modified, and better, version of the example:
  6139.  
  6140. /* 1. Wait until a message arrive: */
  6141. Wait( 1 << my_window->UserPort->mp_SigBit );
  6142.  
  6143.  
  6144. /* As long as we can collect messages successfully we stay */
  6145. /* in the while-loop: */
  6146. while( my_message = GetMsg( my_window->UserPort ) )
  6147. {
  6148.   /* The rest is as normal... */
  6149.  
  6150.  
  6151.   /* 3. We should now examine the IntuiMessage structure, */
  6152.   /*    and save any important values. (If we save the    */
  6153.   /*    information we can reply as soon as possible, and */
  6154.   /*    later examine the values.)                        */
  6155.   class   = my_message->Class;
  6156.   code    = my_message->Code;
  6157.   address = my_message->IAddress;
  6158.   
  6159.  
  6160.   /* 4. We should now reply since we have finished reading */
  6161.   /*    the IntuiMessage structure. (Your program should   */
  6162.   /*    always reply as fast as possible.)                 */
  6163.   ReplyMsg( my_message );
  6164.   
  6165.   
  6166.   /* 5. We can now examine what the message actually was */
  6167.   /*    about: (We have replied so we may NOT examine    */
  6168.   /*    the IntuiMessage structure any more, but we may  */
  6169.   /*    of course check the variables: class, code and   */
  6170.   /*    address.)                                        */
  6171.   switch( class )
  6172.   {
  6173.     case GADGETDOWN: /* A gadget has been pressed.       */
  6174.     case GADGETUP:   /* A gadget has been released.      */
  6175.     case MENUPICK:   /* A menu item has been selected... */
  6176.     /* And so on...                                      */
  6177.   }
  6178. }
  6179.   
  6180. 8.4  IDCMP FLAGS
  6181.  
  6182. We have used several IDCMP flags in the last chapter, such as GADGETDOWN, 
  6183. MENUPICK, REQVERIFY etc, but here is the total list of all IDCMP flags:
  6184.  
  6185. Here are the three IDCMP flags which are closely related to gadgets:
  6186.  
  6187. GADGETDOWN:
  6188.     
  6189. Your program will this message if a gadget has been selected. (Note, the gadget 
  6190. must have the GADGIMMEDIATE flag set in its Activation field. If not there will 
  6191. be no GADGETDOWN message created.)
  6192.  
  6193. GADGETUP:
  6194.     
  6195. Your program will this message if a gadget has been released. (Note, the gadget 
  6196. must have the RELVERIFY flag set in its Activation field. If not there will be 
  6197. no GADGETUP message created.)
  6198.  
  6199. CLOSEWINDOW:
  6200.     
  6201. Your program will receive this message if the user selects the Close Window 
  6202. gadget (System Gadget). Remember, the window will not be automatically closed. 
  6203. It is up to your program if it want to close it or not.
  6204.  
  6205. Here are the three IDCMP flags which are closely related to requesters:
  6206.  
  6207. REQSET:
  6208.     
  6209. Your program will receive this message if a requester has been opened in your 
  6210. window. This is very handy way to detect if a Double-menu requester has been 
  6211. activated in your window. (You will receive a message both when a DM-requester 
  6212. as well as a normal requester has been activated.)
  6213.  
  6214. REQCLEAR:
  6215.     
  6216. This message tells you that a requester has been cleared from your window. 
  6217. Note, you will receive this message only when all requesters in your window has 
  6218. been cleared.
  6219.  
  6220. REQVERIFY:
  6221.     
  6222. Your program will receive this message if a requester is going to be activated. 
  6223. However, the requester will first be displayed once you have replied, and this 
  6224. will therefore allow you to finish of with something before the requester will 
  6225. be activated. Note, your program will only receive this message when the first 
  6226. requester is opening in the window. Intuition will then assume that you have 
  6227. stopped any output to that window.
  6228.  
  6229. Here are the two IDCMP flags which are closely related to menus:
  6230.  
  6231. MENUPICK:
  6232.     
  6233. Your program will receive this message if the user has pressed the right mouse 
  6234. button. (Note, It does not necessarily mean that an item has been selected.) 
  6235. The Code field of the message will contain the menu number. If no item was 
  6236. selected Code will be equal to MENUNULL. Use the Macros described in chapter 7 
  6237. MENUS, to check which menu/item/subitem was selected.
  6238.  
  6239. MENUVERIFY:
  6240.     
  6241. Your program will receive this message if a menu is going to be activated. The 
  6242. menu will, however, first be displayed once you have replied, and this will 
  6243. therefore allow you to finish of with something before the menu will be opened.
  6244.                 
  6245.     
  6246. Check if the Code field of the message is equal to MENUHOT which means it is 
  6247. your menu that will be displayed, or if Code is equal to MENUWAITING, which 
  6248. means that some other window's menustrip will be displayed. You can even cancel 
  6249. the whole menu-operation if you want by changing the Code field to MENUCANCEL 
  6250. before you reply.
  6251.  
  6252. Here are the three IDCMP flags which are closely related to the mouse:
  6253.  
  6254. MOUSEBUTTONS:
  6255.     
  6256. Your program will receive this message if any of the mouse buttons have been 
  6257. pressed or released. Examine the Code field of the message to see if it is 
  6258. equal to:
  6259.  
  6260.     
  6261. SELECTDOWN: The left mouse button has been pressed.
  6262.     
  6263. SELECTUP:   The left mouse button has been released.
  6264.     
  6265. MENUDOWN:   The right mouse button has been pressed.
  6266.     
  6267. MENUUP:     The right mouse button has been released.
  6268.     
  6269. Important! If the user presses the left mouse button while the pointer is 
  6270. somewhere on a gadget's select box, your program will NOT receive any message. 
  6271. Remember also that if the user presses the right mouse button a menu strip will 
  6272. be displayed, and your program will not receive any MENUDOWN message. You need 
  6273. to set the RMBTRAP flag in the NewWindow structure's Flags field in order to 
  6274. receive any right mouse buttons event. (No menu can then be used for that 
  6275. window.)
  6276.  
  6277. MOUSEMOVE:
  6278.     
  6279. Your program will receive this message if the mouse has been moved. Note, your 
  6280. window needs to have the REPORTMOUSE flag set in the NewWindow structure's 
  6281. Flags field, or a gadget in the window needs to have the FOLLOWMOUSE flag set 
  6282. in the Gadget structure's Activation field.
  6283.  
  6284.     
  6285. (Be prepared to receive many messages!)
  6286.  
  6287. DELTAMOVE:
  6288.     
  6289. Same as MOUSEMOVE except that the movements will be reported as delta movements 
  6290. instead of absolute positions. Note, your program will continue to receive 
  6291. delta movements even if the pointer has reached the border of the display.
  6292.  
  6293.     
  6294. (Be prepared to receive many messages!)
  6295.  
  6296. Here are the five IDCMP flags which are closely related to windows:
  6297.  
  6298. NEWSIZE:
  6299.     
  6300. Your program will receive this message if the user has resized the window. 
  6301. Check the windows' Window structure's Width and Height fields to discover the 
  6302. new size.
  6303.  
  6304. SIZEVERIFY:
  6305.     
  6306. Your program will receive this message if the user tries to resize the window. 
  6307. However, Intuition will change the size first when your program has replied, 
  6308. and this allows you to finish of with something before the window will change 
  6309. size.
  6310.  
  6311. REFRESHWINDOW:
  6312.     
  6313. Your program will receive this message if the window needs to be redrawn. This 
  6314. applies only to SIMPLE_REFRESH and SMART_REFRESH windows. Remember, if you 
  6315. receive a REFRESHWINDOW event, you need to call the functions BeginRefresh() 
  6316. and EndReresh() even if you do not redraw anything.
  6317.  
  6318. ACTIVEWINDOW:
  6319.     
  6320. Your program will receive this message if your window is activated.
  6321.  
  6322. INACTIVEWINDOW:
  6323.     
  6324. Your program will receive this message if your window is deactivated.
  6325.  
  6326. Other IDCMP flags:
  6327.  
  6328. RAWKEY:
  6329.     
  6330. Your program will receive this message every time the user presses a key. The 
  6331. Code field of the message will contain the raw keykodes (see Appendix C), and 
  6332. the Qualifier field of the message contains the qualifier (SHIFT, CTRL etc).
  6333.  
  6334. VANILLAKEY:
  6335.     
  6336. Your program will receive this message every time the user presses a key. The 
  6337. Code field of the message will contain the ASCII character (see Appendix D).
  6338.  
  6339. DISKINSERTED:
  6340.     
  6341. Your program will receive this message if a disk is inserted. All interested 
  6342. programs will hear about it.
  6343.  
  6344. DISKREMOVED:
  6345.     
  6346. Your program will receive this message if a disk is removed. All interested 
  6347. programs will hear about it.
  6348.  
  6349. NEWPREFS:
  6350.     
  6351. If the the system Preferences is changed (by the user or another program), your 
  6352. program will receive a NEWPREFS message. Call the function GetPrefs() to get 
  6353. the new system Preferences. (See chapter 9 MISCELLANEOUS for more information 
  6354. about Preferences etc.)
  6355.  
  6356. INTUITICKS:
  6357.     
  6358. Your program will receive this message ten times a second (approximately). 
  6359. However, if you have not replied on the first INTUITICKS message, the next 
  6360. message will not be sent.
  6361.  
  6362. WBENCHMESSAGE:
  6363.     
  6364. If the workbench is opened or closed by a program (calling the functions 
  6365. OpenWorkBench()/CloseWorkBench() your program will receive a WORKBENCHMESSAGE. 
  6366. The Code field of the message will be equal to WBENCHOPEN if the WorkBench was 
  6367. opened, or WBENCHCLOSE if the workbench was closed.
  6368.  
  6369. 8.5  FUNCTIONS
  6370.  
  6371. GetMsg()
  6372.  
  6373. This function tries to get a message from a message port.
  6374.  
  6375. Synopsis:
  6376.     
  6377. my_message = GetMsg( my_message_port );
  6378.  
  6379. my_message:
  6380.     
  6381. (struct Message *) Pointer to a Message structure, in this case a pointer to an 
  6382. IntuiMessage structure, or NULL if no message was collected.
  6383.  
  6384. my_message_port:
  6385.     
  6386. (struct MsgPort *) Pointer to an MsgPort. If you have opened a window, you can 
  6387. find your window's message port in the Window structure. ( my_window->UserPort 
  6388.  
  6389. ReplyMsg()
  6390.  
  6391. This function tells Intuition that you have finished reading the message. 
  6392. Remember, once you have replied you may not examine or change the IntuiMessage 
  6393. structure any more.
  6394.   
  6395. Synopsis:   ReplyMsg( my_message );
  6396.   
  6397. my_message:
  6398.     
  6399. (struct Message *) Pointer to a Message structure, in this case a pointer to an 
  6400. IntuiMessage structure.
  6401.  
  6402. ModifyIDCMP()
  6403.  
  6404. This function changes the Window structure's IDCMPFlags field.
  6405.  
  6406. Synopsis:
  6407.     
  6408. ModifyIDCMP( my_window, IDCMPFlags );
  6409.   
  6410. my_window:
  6411.     
  6412. (struct Window *) Pointer to an already opened window.
  6413. IDCMPFlags:
  6414.     
  6415. (long) None or more IDCMP flags.
  6416.  
  6417. If you call this function with no IDCMP flags set, the window's IDCMP Ports 
  6418. will be closed. On the other hand, if you call this function, with one or more 
  6419. IDCMP flags set, a Port will be, if necessary, opened for you.
  6420.  
  6421.  
  6422. 8.6  EXAMPLES
  6423.  
  6424. See the examples in chapter 4 (GADGETS) to 7 (MENUS). They will explain how to 
  6425. use the IDCMP flags: GADGETDOWN, GADGETUP, CLOSEWINDOW, REQSET, REQCLEAR, 
  6426. REQVERIFY, MENUPICK and MENUVERIFY.
  6427.  
  6428. Example 1
  6429. This program explains how to use the IDCMP flag MOUSEBUTTONS.
  6430.  
  6431. Example 2
  6432. This program explains how to use the IDCMP flag MOUSEMOVE.
  6433.  
  6434. Example 3
  6435. This program explains how to use the IDCMP flags: NEWSIZE, ACTIVEWINDOW and 
  6436. INACTIVEWINDOW.
  6437.  
  6438. Example 4
  6439. This program explains how to use the IDCMP flag SIZEVERIFY.
  6440.  
  6441. Example 5
  6442. This program explains how to use the IDCMP flag RAWKEY.
  6443.  
  6444. Example 6
  6445. This program explains how to use the IDCMP flag VANILLAKEY.
  6446.  
  6447. Example 7
  6448. This program explains how to use the IDCMP flags: DISKINSERTED and DISKREMOVED.
  6449.  
  6450. Example 8
  6451. This program explains how to use the IDCMP flag INTUITICKS.
  6452.  
  6453. Example 9
  6454. This program explains how to use the IDCMP flag REFRESHWINDOW, and how to 
  6455. optimize the redrawing of the window.
  6456.  
  6457.  
  6458. MISCELLANEOUS
  6459.  
  6460. 9.1  INTRODUCTION
  6461.  
  6462. This is the last chapter about Intuition, and we will therefore finish of by 
  6463. discussing some special features.
  6464.  
  6465. 9.2  MEMORY
  6466.  
  6467. If you write C programs you will often need to allocate some memory. This 
  6468. process is normally referred as "dynamic memory allocation" and is used 
  6469. whenever your program needs some more memory while it is running.
  6470.  
  6471. When you allocate memory you need to specify how much you want, and what type 
  6472. of memory (Fast or Chip). "Exec" will then try to allocated the memory, and 
  6473. will return a pointer to the memory, or NULL if it could not find a block big 
  6474. enough.
  6475.  
  6476. Once you have allocated the memory, you can use it as much as you want. You 
  6477. just have to remember that before the program terminates it must have 
  6478. deallocated all allocated memory. If you forget to deallocate the memory when 
  6479. you leave, it will be lost, and the only way to get it back is to reboot.
  6480.  
  6481. 9.2.1  ALLOCATE MEMORY
  6482.  
  6483. You usually use the function AllocMem() if you want to allocate memory. You 
  6484. only need to specify how much memory you need, and what type of memory (Chip, 
  6485. Fast etc), and AllocMem() will return a pointer to the new memory, or NULL if 
  6486. no memory could be allocated.
  6487.  
  6488. Synopsis
  6489. :
  6490.     
  6491. memory = AllocMem( size, type );
  6492.  
  6493. memory:
  6494.     
  6495. (void *) Pointer to the new allocated memory, or NULL if no memory could be 
  6496. allocated. Remember! Never use memory which you have not successfully 
  6497. allocated.
  6498.  
  6499. size:
  6500.     
  6501. (long) The size (in bytes) of the memory you want. (AllocMem() always allocates 
  6502. memory in multiples of eight bytes. So if you only ask for 9 bytes, Exec would 
  6503. actually give you 16 Bytes (2*8).)
  6504.  
  6505. type:
  6506.     
  6507. (long) You need to choose one of the three following types of memory (see 
  6508. chapter 0 INTRODUCTION for more information about Chip and Fast memory). (The 
  6509. flags are declared in the header file "exec/memory.h".)
  6510.  
  6511.     
  6512. MEMF_CHIP   Chip memory. This memory can be accessed by both the main 
  6513. processor, as well as Chips. Graphics/Sound data MUST  therefore be placed in 
  6514. Chip memory. If it does not matter what type of memory you get (Fast or Chip), 
  6515. you should try to allocate Fast memory before you allocate Chip memory. (Chip 
  6516. memory is more valuable than Fast memory.)
  6517.  
  6518.     
  6519. MEMF_FAST   Fast memory. This memory can only be accessed by the main 
  6520. processor. (Graphics and Sound data can NOT be stored in Fast memory, use Chip 
  6521. memory.) This memory is normally a little bit faster than Chip memory, since 
  6522. only the main processor is working with it, and it is not disturbed by the 
  6523. Chips.
  6524.  
  6525.     
  6526. MEMF_PUBLIC If it does not matter what type of memory you get (you do not 
  6527. intend to use the memory for Graphics/Sound data), you should use Fast memory. 
  6528. However, all Amigas do not have Fast memory, since you need to by a memory 
  6529. expansion in order to get it. If want to tell Exec that you would like to use 
  6530. Fast memory if there is any, else use Chip memory, you should ask for 
  6531. MEMF_PUBLIC.
  6532.  
  6533.     
  6534. If you want the allocated memory to be cleared (initialized to zeros), you 
  6535. should set  MEMF_CLEAR.
  6536.  
  6537. If you need to allocate 150 bytes of Chip memory, you would write:
  6538.  
  6539. /* Declare a pointer to the memory you are going to allocate: */
  6540. CPTR memory; /* CPTR means memory pointer, declared in the    */
  6541.              /* header file "exec/types.h". "exec/types.h" is */
  6542.              /* automatically included when you include the   */
  6543.              /* header file "intuition/intuition.h".          */
  6544.  
  6545. /* Allocate 150 bytes of Chip memory: */
  6546. memory = (CPTR) AllocMem( 150, MEMF_CHIP );
  6547.  
  6548. /* Have we allocated the memory successfully? */
  6549. if( memory == NULL )
  6550.   /* ERROR! Have not allocated any memory! */
  6551.  
  6552. 9.2.2  DEALLOCATE MEMORY
  6553.  
  6554. All memory that has been allocated MUST be deallocated before your program 
  6555. terminates. If you forget to deallocate memory which you have allocated, that 
  6556. memory would be forever lost. The only way of freeing such memory is to reboot. 
  6557. (Not to be recommended. We are not Demo-writers, are we?)
  6558.  
  6559. You free allocated memory by calling the function FreeMem():
  6560.  
  6561. Synopsis
  6562. :
  6563.     
  6564. FreeMem( memory, size );
  6565.  
  6566. memory:
  6567.     
  6568. (void *) Pointer to some memory which has previously been allocated. Remember! 
  6569. Never deallocate memory, which you have not allocated, and never use memory 
  6570. which has been deallocated.
  6571.  
  6572. size:
  6573.     
  6574. (long) The size (in bytes) of the memory you want to deallocate.
  6575.  
  6576. To deallocate the 150 bytes of Chip memory we have previously allocated, we 
  6577. write:
  6578.  
  6579. /* Free 150 bytes of memory: */
  6580. FreeMem( memory, 150 );
  6581.  
  6582. 9.2.3  REMEMBER MEMORY
  6583.  
  6584. If you allocate memory several times, and in different quantities, it can be 
  6585. very hard to remember to deallocate all memory correctly. However, do not 
  6586. despair. Intuition have a solution for you. You can use the function 
  6587. AllocRemember() which calls the function AllocMem(), but will also allocate 
  6588. memory for a Remember structure which is automatically initialized for you. 
  6589. Every time you allocate memory with the AllocRemember() function, the Remember 
  6590. structures are linked together, and the information about the memory (size and 
  6591. position) is remembered. Once you want to deallocate the memory, you only need 
  6592. to call the function FreeRemember(), and all memory is deallocated for you 
  6593. automatically.
  6594. The Remember structure look like this:
  6595. struct Remember
  6596. {
  6597.   struct Remember *NextRemember;
  6598.   ULONG RememberSize;
  6599.   UBYTE *Memory;
  6600. };
  6601.  
  6602. The AllocRemember() function is called like this: (Very similar to the 
  6603. AllocMem() function.)
  6604.  
  6605. Synopsis
  6606. :
  6607.     
  6608. memory = AllocRemember( remember, size, type );
  6609.  
  6610. memory:
  6611.     
  6612. (char *) Pointer to the new allocated memory, or NULL if no memory could be 
  6613. allocated. Remember! Never use memory which you have not successfully 
  6614. allocated.
  6615.  
  6616. remember:
  6617.     
  6618. (struct Remember **) Address of a pointer to a Remember structure. Before you 
  6619. call the AllocRemember() function for the first time you should set this 
  6620. pointer to NULL. (Note that it is a pointer to a pointer!)
  6621.  
  6622. size:›
  6623.     
  6624. (long) The size (in bytes) of the memory you want. (AllocMem() always allocates 
  6625. memory in multiples of eight bytes. So if you only ask for 29 bytes, Exec would 
  6626. actually give you 32 Bytes (4*8).)
  6627.  
  6628. type:
  6629.     
  6630. (long) You need to choose one of the three following types of memory (see 
  6631. chapter 0 INTRODUCTION for more information about Chip and Fast memory):
  6632.  
  6633.     
  6634. MEMF_CHIP   Chip memory. This memory can be accessed by both the main 
  6635. processor, as well as the Chips. Graphics/Sound data MUST therefore be placed 
  6636. in Chip memory. If it does not matter what type of memory you get (Fast or 
  6637. Chip), you should try to allocate Fast memory before you allocate Chip memory. 
  6638. (Chip memory is more valuable than Fast memory.)
  6639.  
  6640.     
  6641. MEMF_FAST   Fast memory. This memory can only be accessed by the main 
  6642. processor. (Graphics and Sound data can NOT be stored in Fast memory, use Chip 
  6643. memory.) This memory is normally a little bit faster than Chip memory, since 
  6644. only the main processor is working with it, and it is not disturbed by the 
  6645. Chips.
  6646.  
  6647.     
  6648. MEMF_PUBLIC If it does not matter what type of memory you get (you do not 
  6649. intend to use the memory for Graphics/Sound data), you should use Fast memory. 
  6650. However, all Amigas do not have Fast memory, since you need to by a memory 
  6651. expansion in order to get it. If want to tell Exec that you would like to use 
  6652. Fast memory if there is any, else use Chip memory, you should ask for 
  6653. MEMF_PUBLIC.
  6654.  
  6655.     
  6656. If you want the allocated memory to be cleared (initialized to zeros), you 
  6657. should set MEMF_CLEAR.
  6658.  
  6659. When you want to deallocate the memory you only need to call the function 
  6660. FreeRemember() function. You can if you want, deallocate only the Remember 
  6661. structures, and take care of the deallocation yourself, but be careful. The 
  6662. FreeRemember() function is called like this:
  6663.  
  6664.  
  6665. Synopsis
  6666. :
  6667.     
  6668. FreeRemember( remember, everything );
  6669.  
  6670. remember:
  6671.     
  6672. (struct Remember **) Address of a pointer to the first Remember structure 
  6673. (initialized by the AllocRemember() function). (Note that it is a pointer to a 
  6674. pointer!)
  6675.  
  6676. everything:
  6677.     
  6678. (long) A boolean value. If everything is equal to TRUE, all memory (both the 
  6679. allocated memory and the Remember structures) are deallocated. However, if 
  6680. everything is equal to FALSE, only the Remember structures are deallocated, and 
  6681. you have to deallocate the memory yourself.
  6682.  
  6683.  
  6684. Here is a short example which shows how to use the AllocRemember(), and the 
  6685. FreeRemember() functions:
  6686.  
  6687. struct Remember *remember = NULL;
  6688. CPTR memory1, memory2, memory3;
  6689.  
  6690. /* Allocate 350 bytes of Chip memory, which is cleared: */
  6691. memory1 = AllocRemember( &remember, 350, MEMF_CHIP|MEMF_CLEAR );
  6692.  
  6693. if( memory1 == NULL )
  6694.   Clean up and leave;
  6695.  
  6696. /* Allocate 900 bytes of memory (any type, Fast if possible): */
  6697. memory2 = AllocRemember( &remember, 900, MEMF_PUBLIC );
  6698.  
  6699. if( memory2 == NULL )
  6700.   Clean up and leave;
  6701.  
  6702. /* Allocate 100 bytes of Chip memory: *
  6703. memory3 = AllocRemember( &remember, 100, MEMF_CHIP );
  6704.  
  6705. if( memory3 == NULL )
  6706.   Clean up and leave;
  6707.  
  6708. ...
  6709.  
  6710.  
  6711. /* Deallocate all memory with one single call: */
  6712. FreeRemember( &remember, TRUE );
  6713.  
  6714.  
  6715. If we wanted, we could have deallocated all Remember
  6716. structures, and then deallocate the memory ourself with help
  6717. of the normal FreeMem() function:
  6718.  
  6719. /* Deallocate only the Remember structures: */
  6720. FreeRemember( &remember, FALSE );
  6721. FreeMem( memory1, 350 );
  6722. FreeMem( memory2, 900 );
  6723. FreeMem( memory3, 100 );
  6724.  
  6725. 9.3  PREFERENCES
  6726.  
  6727. When the system starts up, Intuition is initialized to some default values. 
  6728. However, if there exist a file called: "system-configuration" in the "devs" 
  6729. directory on the system disk, that file is used to set the system values, 
  6730. instead of the default values.
  6731. The user can with the "Preferences" program change the system values, and/or 
  6732. the "system-configuration" file. If the user selects the "USE" command, only 
  6733. the system values are changed, while if the user selects the "SAVE" command, 
  6734. both the system values, as well as the "system-configuration" file are updated.
  6735.  
  6736. Your program can get a copy of the system values by calling the function 
  6737. GetPrefs(). If you want to get a copy of the default values you use the 
  6738. function GetDefPrefs(). When you get a copy of the Preferences data, you can 
  6739. decide how much data you want copied. You can therefore, if you want, only copy 
  6740. parts of the structure, and do not need to allocate memory for the whole 
  6741. structure. The most important values are because of that placed in the 
  6742. beginning of the structure. The Preferences structure look like this: (See file 
  6743. "intuition/preferences.h" for more information. It is on the fourth Lattice C 
  6744. disk, in the "Compiler_Headers" directory.)
  6745.  
  6746. struct Preferences
  6747. {
  6748.   BYTE FontHeight;
  6749.   UBYTE PrinterPort;
  6750.   USHORT BaudRate;
  6751.   struct timeval KeyRptSpeed;
  6752.   struct timeval KeyRptDelay;
  6753.   struct timeval DoubleClick;
  6754.   USHORT PointerMatrix[POINTERSIZE];
  6755.   BYTE XOffset;
  6756.   BYTE YOffset;
  6757.   USHORT color17;
  6758.   USHORT color18;
  6759.   USHORT color19;
  6760.   USHORT PointerTicks;
  6761.   USHORT color0;
  6762.   USHORT color1;
  6763.   USHORT color2;
  6764.   USHORT color3;
  6765.   BYTE ViewXOffset;
  6766.   BYTE ViewYOffset;
  6767.   WORD ViewInitX, ViewInitY;
  6768.   BOOL EnableCLI;
  6769.   USHORT PrinterType;
  6770.   UBYTE PrinterFilename[FILENAME_SIZE];
  6771.   USHORT PrintPitch;
  6772.   USHORT PrintQuality;
  6773.   USHORT PrintSpacing;
  6774.   UWORD PrintLeftMargin;
  6775.   UWORD PrintRightMargin;
  6776.   USHORT PrintImage;
  6777.   USHORT PrintAspect;
  6778.   USHORT PrintShade;
  6779.   WORD PrintThreshold;
  6780.   USHORT PaperSize;
  6781.   UWORD PaperLength;
  6782.   USHORT PaperType;
  6783.   UBYTE SerRWBits;
  6784.   UBYTE SerStopBuf;
  6785.   UBYTE SerParShk;
  6786.   UBYTE LaceWB;
  6787.   UBYTE WorkName[FILENAME_SIZE];
  6788.   BYTE RowSizeChange;
  6789.   BYTE ColumnSizeChange;
  6790.   UWORD PrintFlags;
  6791.   UWORD PrintMaxWidth;
  6792.   UWORD PrintMaxHeight;
  6793.   UBYTE PrintDensity;
  6794.   UBYTE PrintXOffset;
  6795.   UWORD wb_Width;
  6796.   UWORD wb_Height;
  6797.   UBYTE wb_Depth;
  6798.   UBYTE ext_size;
  6799. };
  6800.  
  6801. You call the function GetPrefs() like this:
  6802.  
  6803. Synopsis:
  6804.     
  6805. pref = GetPrefs( buffer, size );
  6806.  
  6807. pref:
  6808.     
  6809. (struct Preferences *) Pointer to your preferences. Same as your memory pointer 
  6810. (buffer), but is returned so you can check if you got a copy or not. If you 
  6811. could not get a copy of the preferences, the function returns NULL.
  6812.  
  6813. buffer:
  6814.     
  6815. (struct Preferences *) Pointer to the memory buffer which should be used to 
  6816. store a copy of the preferences in.
  6817.  
  6818. size:
  6819.     
  6820. (long) The number of bytes you want to copy to the buffer. Important, the 
  6821. buffer must be at least as big as the number of bytes you want to copy.
  6822.  
  6823. You call the function GetDefPrefs() like this:
  6824.  
  6825. Synopsis:
  6826.     
  6827. pref = GetPrefs( buffer, size );
  6828.  
  6829. pref:
  6830.     
  6831. (struct Preferences *) Pointer to the default preferences. If the function 
  6832. could not make a copy of the preferences, the function returns NULL.
  6833.  
  6834. buffer:
  6835.     
  6836. (struct Preferences *) Pointer to the memory buffer which should be used to 
  6837. store a copy of the default preferences in.
  6838.  
  6839. size:
  6840.     
  6841. (long) The number of bytes you want to copy to the buffer. Important, the 
  6842. buffer must be at least as big as the number of bytes you want to copy.
  6843.  
  6844. Here is an example on how to get a copy of the current preferences:
  6845.  
  6846. /* Declare a preferences structure: */
  6847. struct Preferences pref;
  6848.  
  6849. /* Try to get a copy of the current preferences: */
  6850. if( GetPrefs( &pref, sizeof(pref) ) == NULL )
  6851.   /* Could not get a copy of the preferences! */
  6852.  
  6853. Once you have got a copy of the current/default preferences we can start to 
  6854. check the settings.
  6855.  
  6856. You can, if you want, change some values, and then save them as new 
  6857. preferences. IMPORTANT! You should never mess with the settings since it is the 
  6858. user's own preferences, and should therefore NOT be changed unless the user 
  6859. really WANT to alter them.
  6860.  
  6861. You set new preferences by calling the function SetPrefs():
  6862.  
  6863. Synopsis:
  6864.     
  6865. SetPrefs( pref, size, doit );
  6866.  
  6867. pref:
  6868.     
  6869. (struct Preferences *) Pointer to your modified Preferences structure.
  6870.  
  6871. size:
  6872.     
  6873. (long) The number of bytes you want to change.
  6874.  
  6875. doit:
  6876.     
  6877. (long) Boolean value which if FALSE, changes the preferences, but will not send 
  6878. a NEWPREFS message. If doit is equal to TRUE, the settings will be changed, and 
  6879. a NEWPREFS message will be sent. As long as the user is changing the values, 
  6880. doit should be FALSE, but when the user has finished, set it to TRUE, and all 
  6881. programs will get a NEWPREFS message. 
  6882.  
  6883. 9.4  WARNINGS
  6884.  
  6885. There exist three levels of warnings you can give the user when something goes 
  6886. wrong:
  6887.  
  6888. 1. If you just want to get the users attention about something, but nothing 
  6889. really dangerous has happened, you should call the function DisplayBeep(). It 
  6890. will flash the colours of the screen.
  6891.  
  6892. Synopsis:
  6893.     
  6894. DisplayBeep( screen );
  6895.    
  6896. screen:›
  6897.     
  6898. (struct Screen *) Pointer to the screen, which colours you want to flash. If 
  6899. you have not opened a screen yourself (you are using the Workbench Screen), you 
  6900. can find a pointer to that screen in the Window structure: (my_window is a 
  6901. pointer to an opened window) DisplayBeep( my_window->WScreen );
  6902.  
  6903. 2. If something important has happened, or if you want the user to take some 
  6904. action (select something) etc, open a Requester. (See chapter 5 REQUESTERS for 
  6905. more information.)
  6906.  
  6907. 3. If something TERRIBLE is happening, the system is breaking down, open an 
  6908. Alert. (See chapter 6 ALERTS for more information.)
  6909.  
  6910. 9.5  DOUBLE CLICK
  6911.  
  6912. There are five different mouse actions:
  6913.  
  6914. 1. Press a button
  6915.     
  6916. The user can press on a button.
  6917. 2. Release a button
  6918.     
  6919. The user can release a previously pressed button.
  6920. 3. Click a button
  6921.     
  6922. Quickly pressing and releasing a button.
  6923. 4. Double-click a button
  6924.     
  6925. Quickly pressing/releasing a button twice.
  6926. 5. Drag
  6927.     
  6928. Hold a button pressed, while moving the mouse.
  6929.  
  6930. Use the IDCMP flags SELECTDOWN, SELECTUP, MENUDOWN, and MENUUP in order to 
  6931. receive mouse-buttons events. (See chapter 8 IDCMP for more information.)
  6932.  
  6933. If you want to check if the user double-clicked one of the mouse buttons, you 
  6934. can use the function DoubleClick(). You give the function the current as well 
  6935. as the previous time when the button was pressed, and it will check the 
  6936. preferences and return TRUE if the two button events happened within the time 
  6937. limit. (The user can change the time limit for double-clicking events.)
  6938. Synopsis
  6939. :
  6940.     
  6941. double = DoubleClick( sec1, mic1, sec2, mic2 );
  6942.  
  6943. double:
  6944.     
  6945. (long) If the two button events happened within the current time limit, the 
  6946. function will return TRUE, else it will return FALSE.
  6947.  
  6948. sec1:
  6949.     
  6950. (long) Time (seconds) when the button was pressed for the first time.
  6951.  
  6952. mic1:
  6953.     
  6954. (long) Time (micros) when the button was pressed for the first time.
  6955.  
  6956. sec2:
  6957.     
  6958. (long) Current time (seconds).
  6959.  
  6960. mic2:
  6961.     
  6962. (long) Current Time (micros).
  6963.  
  6964. Here is a short example on how to check double-click events:
  6965.  
  6966. struct IntuiMessage *message;
  6967. ULONG sec1, mic1, sec2, mic2; 
  6968.  
  6969. ... ... ...
  6970.  
  6971. if( message->Class == MOUSEBUTTONS )
  6972. {
  6973.   /* A mouse button was pressed/released. */
  6974.   if( message->Code == SELECTDOWN )
  6975.   {
  6976.     /* The left mouse button was pressed. */
  6977.  
  6978.     /* Save the old time: */
  6979.     sec2 = sec1;
  6980.     mic2 = mic1;
  6981.     
  6982.     /* Get the new time: */
  6983.     sec1 = message->Seconds;
  6984.     mic1 = message->Micros;
  6985.     
  6986.     /* Check if it was a double-click or not: */
  6987.     if( DoubleClick( sec2, mic2, sec1, mic1 ) )
  6988.     {
  6989.       printf("Double-Click!\n");
  6990.       /* Reset the values: */
  6991.       sec1 = 0;
  6992.       mic1 = 0;
  6993.     }
  6994.   }
  6995. }
  6996.  
  6997. 9.6  TIME
  6998.  
  6999. You can get the current time by calling the function CurrentTime():
  7000.  
  7001. Synopsis
  7002. :
  7003.     
  7004. CurrentTime( seconds, micros );
  7005.  
  7006. seconds:
  7007.     
  7008. (long *) Pointer to an ULONG variable which will be initialized with the 
  7009. current seconds stamp.
  7010.  
  7011. micros:
  7012.     
  7013. (long *) Pointer to an ULONG variable which will be initialized with the 
  7014. current micros stamp.
  7015.  
  7016. Here is a short example:
  7017.  
  7018. ULONG seconds, micros;
  7019.  
  7020. CurrentTime( &seconds, µs );
  7021.  
  7022. 9.7  STYLE
  7023.  
  7024. Since Intuition is the interface between computer and the user, it is important 
  7025. that there are some standards concerning gadgets, requesters, menus, mouse, 
  7026. etc. If similar programs use the same type of style, the user will much faster 
  7027. learn to handle them. You, as the programmer, have therefore to make sure that 
  7028. your program is easily understandable and foolproof. Make your program easy to 
  7029. learn, and fun to handle!
  7030.  
  7031. 9.7.1  GADGETS
  7032.  
  7033. Remember to make the gadgets easily recognizable, and understandable. Put short 
  7034. words like "CANCEL", "OK" in the gadget, or use graphics symbols. Remember to 
  7035. disable (ghosted) a gadget when it becomes nonfunctional.
  7036.  
  7037. 9.7.2  REQUESTERS
  7038.  
  7039. Requesters have two main functions: They can inform the user about something, 
  7040. and/or ask the user to take some action. It is therefore important that it is 
  7041. easy for the user to understand what has or will happen, and what he/she has to 
  7042. do. Use colourful graphics if necessary, and remember that if you want some 
  7043. action from the user, always give him/her a way out without affecting anything 
  7044. (CANCEL).
  7045.  
  7046. A requester which is meaningless should be taken away. Use the functions 
  7047. EndRequest(), ClearDMRequest().
  7048.  
  7049. Place the OK/YES/TRUE gadget (if there exist one) in the bottom left corner, 
  7050. and the CANCEL/NO/FALSE gadget in the bottom right corner. There should always 
  7051. be an escape (CANCEL) gadget in every requester!
  7052.  
  7053. ---------------------------
  7054. | OK to delete file?      |
  7055. |                         |
  7056. | ----------   ---------- |
  7057. | | DELETE |   | CANCEL | |
  7058. | ----------   ---------- |
  7059. ---------------------------
  7060. 9.7.3  MENUS
  7061.  
  7062. Menu items/subitems which are nonfunctional should be disabled (ghosted). Use 
  7063. the function OffMenu().
  7064.  
  7065. There are two menus, project and edit menu, which many program will use, and 
  7066. should therefore look something like this:
  7067.  
  7068. PROJECT
  7069.  
  7070. Item      Function
  7071. ---------------------------------------------------------------
  7072. New       Creates a new project.
  7073. Open      Opens an old project.
  7074. Save      Saves current project.
  7075. Save as   Saves current project under a new name.
  7076. Print     Prints the whole project.
  7077. Print as  Prints parts of a project, and/or with new settings.
  7078. Quit      Quits. Remember to ask the user if he/she really
  7079.           wants to quit, and if he/she wants to save the
  7080.           project. 
  7081.  
  7082.  
  7083. EDIT
  7084.  
  7085. Item      Function
  7086. ---------------------------------------------------------------
  7087.  
  7088. Undo      Undoes the last operation.
  7089. Cut       Cuts a part away, and stores it in the Clipboard. 
  7090. Copy      Copies a part of the project into the Clipboard.
  7091. Paste     Puts a copy of the Clipboard into the project.
  7092. Erase     Deletes a part of the project without putting it into
  7093.           the Clipboard.
  7094.  
  7095. Remember to enable shortcuts for often used menu-functions. Here are some 
  7096. standard command key styles:
  7097.  
  7098. Amiga + key  Function
  7099. ---------------------------------------------------------------
  7100.  
  7101.   N          New
  7102.   O          Open
  7103.   S          Save
  7104.   Q          Quit
  7105.  
  7106.   U          Undo
  7107.   X          Cut
  7108.   C          Copy
  7109.   P          Past
  7110.  
  7111. 9.7.4  MOUSE
  7112.  
  7113. The left mouse button is used for "selection", while the right mouse button is 
  7114. used for "information transfer". The left mouse button is therefore used for 
  7115. selecting gadgets etc, while menu functions and double-menu requesters etc, use 
  7116. the right mouse button.
  7117.  
  7118.  
  7119. 9.8  FUNCTIONS
  7120.  
  7121. AllocMem()
  7122.  
  7123. This function allocates memory. You specifies what type and how much you want, 
  7124. and it returns a pointer to the allocated memory, or NULL if there did not 
  7125. exist enough memory.
  7126.  
  7127. Synopsis:
  7128.     
  7129. memory = AllocMem( size, type );
  7130.  
  7131. memory:›
  7132.     
  7133. (void *) Pointer to the new allocated memory, or NULL if no memory could be 
  7134. allocated. Remember! Never use memory which you have not successfully 
  7135. allocated.
  7136.  
  7137. size:
  7138.     
  7139. (long) The size (in bytes) of the memory you want. (AllocMem() always allocates 
  7140. memory in multiples of eight bytes. So if you only ask for 9 bytes, Exec would 
  7141. actually give you 16 Bytes (2*8).)
  7142.  
  7143. type:
  7144.     
  7145. (long) You need to choose one of the three following types of memory (see 
  7146. chapter 0 INTRODUCTION for more information about Chip and Fast memory):
  7147.  
  7148.     
  7149. MEMF_CHIP   Chip memory. This memory can be accessed by both the main 
  7150. processor, as well as the Chips. Graphics/Sound data MUST therefore be placed 
  7151. in Chip memory. If it does not matter what type of memory you get (Fast or 
  7152. Chip), you should try to allocate Fast memory before you allocate Chip memory. 
  7153. (Chip memory is more valuable than Fast memory.)
  7154.  
  7155.     
  7156. MEMF_FAST   Fast memory. This memory can only be accessed by the main 
  7157. processor. (Graphics and Sound data can NOT be stored in Fast memory, use Chip 
  7158. memory.) This memory is normally a little bit faster than Chip memory, since 
  7159. only the main processor is working with it, and it is not disturbed by the 
  7160. Chips.
  7161.  
  7162.     
  7163. MEMF_PUBLIC If it does not matter what type of memory you get (you do not 
  7164. intend to use the memory for Graphics/Sound data), you should use Fast memory. 
  7165. However, all Amigas do not have Fast memory, since you need to by a memory 
  7166. expansion in order to get it. If want to tell Exec that you would like to use 
  7167. Fast memory if there is any, else use Chip memory, you should ask for 
  7168. MEMF_PUBLIC.
  7169.  
  7170.     
  7171. If you want the allocated memory to be cleared (initialized to zeros), you 
  7172. should set the flag MEMF_CLEAR.
  7173.  
  7174. FreeMem()
  7175.  
  7176. This function deallocated previously allocated memory. Remember to deallocate 
  7177. all memory you have taken, and never deallocate memory which you have not 
  7178. taken.
  7179.  
  7180. Synopsis:›
  7181.     
  7182. FreeMem( memory, size );
  7183.  
  7184. memory:
  7185.     
  7186. (void *) Pointer to some memory which has previously been allocated. Remember! 
  7187. never use memory which has been deallocated.
  7188.  
  7189. size:
  7190.     
  7191. (long) The size (in bytes) of the memory you want to deallocate.
  7192.  
  7193.  
  7194.  
  7195. AllocRemember()
  7196.  
  7197. This function allocates both memory (same as AllocMem), but will also allocate 
  7198. space for a Remember structure which are initialized with the size of the 
  7199. allocated memory, and a pointer to that memory. Each time the program allocates 
  7200. memory with this function, the Remember structures are linked together.
  7201.   
  7202. Since the Remember structures contains all necessary information about the 
  7203. memory, and are linked together, all memory can be deallocated with one single 
  7204. function call (FreeRemember()).
  7205.  
  7206. Synopsis:
  7207.     
  7208. memory = AllocRemember( remember, size, type );
  7209.  
  7210. memory:
  7211.     
  7212. (char *) Pointer to the new allocated memory, or NULL if no memory could be 
  7213. allocated. Remember! Never use memory which you have not successfully 
  7214. allocated.
  7215.  
  7216. remember:
  7217.     
  7218. (struct Remember **) Address of a pointer to a Remember structure. Before you 
  7219. call the AllocRemember() function for the first time you should set this 
  7220. pointer to NULL. (Note that it is a pointer to a pointer!)
  7221.  
  7222. size:
  7223.     
  7224. (long) The size (in bytes) of the memory you want. (AllocMem() always allocates 
  7225. memory in multiples of eight bytes. So if you only ask for 9 bytes, Exec would 
  7226. actually give you 16 Bytes (2*8).)
  7227.  
  7228. type:
  7229.     
  7230. (long) You need to choose one of the three following types of memory (see 
  7231. chapter 0 INTRODUCTION for more information about Chip and Fast memory):
  7232.  
  7233.     
  7234. MEMF_CHIP   Chip memory. This memory can be accessed by both the main 
  7235. processor, as well as the Chips. Graphics/Sound data MUST therefore be placed 
  7236. in Chip memory. If it does not matter what type of memory you get (Fast or 
  7237. Chip), you should try to allocate Fast memory before you allocate Chip memory. 
  7238. (Chip memory is more valuable than Fast memory.)
  7239.  
  7240.     
  7241. MEMF_FAST   Fast memory. This memory can only be accessed by the main 
  7242. processor. (Graphics and Sound data can NOT be stored in Fast memory, use Chip 
  7243. memory.) This memory is normally a little bit faster than Chip memory, since 
  7244. only the main processor is working with it, and it is not disturbed by the 
  7245. Chips.
  7246.  
  7247.     
  7248. MEMF_PUBLIC If it does not matter what type of memory you get (you do not 
  7249. intend to use the memory for Graphics/Sound data), you should use Fast memory. 
  7250. However, all Amigas do not have Fast memory, since you need to by a memory 
  7251. expansion in order to get it. If want to tell Exec that you would like to use 
  7252. Fast memory if there is any, else use Chip memory, you should ask for 
  7253. MEMF_PUBLIC.
  7254.  
  7255.     
  7256. If you want the allocated memory to be cleared (initialized to zeros), you 
  7257. should set the flag MEMF_CLEAR.
  7258.  
  7259. FreeRemember()
  7260.  
  7261. This function deallocates all memory which has been allocated by the 
  7262. AllocRemember() function. Note, you can deallocate all Remember structures 
  7263. only, and deallocate the memory yourself, if you want to.
  7264.  
  7265. Synopsis:
  7266.     
  7267. FreeRemember( remember, everything );
  7268.  
  7269. remember:
  7270.     
  7271. (struct Remember **) Address of a pointer to the first Remember structure 
  7272. (initialized by the AllocRemember() function). (Note that it is a pointer to a 
  7273. pointer!)
  7274.  
  7275. everything:
  7276.     
  7277. (long) A boolean value. If everything is equal to TRUE, all memory (both the 
  7278. allocated memory and the Remember structures) are deallocated. However, if 
  7279. everything is equal to FALSE, only the Remember structures are deallocated, and 
  7280. you have to deallocate the memory yourself.
  7281.  
  7282. GetPrefs()
  7283.  
  7284. This function makes a copy of the Preferences structure.
  7285.  
  7286. Synopsis:
  7287.     
  7288. pref = GetPrefs( buffer, size );
  7289.  
  7290. pref:
  7291.     
  7292. (struct Preferences *) Pointer to your preferences. Same as your memory pointer 
  7293. (buffer), but is returned so you can check if you got a copy or not. If you 
  7294. could not get a copy of the preferences, the function returns NULL.
  7295.  
  7296. buffer:
  7297.     
  7298. (struct Preferences *) Pointer to the memory buffer which should be used to 
  7299. store a copy of the preferences in.
  7300.  
  7301. size:
  7302.     
  7303. (long) The number of bytes you want to copy to the buffer. Important, the 
  7304. buffer must be at least as big as the number of bytes you want to copy.
  7305.  
  7306. GetDefPrefs()
  7307.  
  7308. This function makes a copy of the default Preferences structure.
  7309.  
  7310. Synopsis:
  7311.     
  7312. pref = GetPrefs( buffer, size );
  7313.  
  7314. pref:
  7315.     
  7316. (struct Preferences *) Pointer to the default preferences. If the function 
  7317. could not make a copy of the preferences, the function returns NULL.
  7318.  
  7319. buffer:
  7320.     
  7321. (struct Preferences *) Pointer to the memory buffer which should be used to 
  7322. store a copy of the default preferences in.
  7323.  
  7324. size:
  7325.     
  7326. (long) The number of bytes you want to copy to the buffer. Important, the 
  7327. buffer must be at least as big as the number of bytes you want to copy.
  7328.  
  7329. SetPrefs()
  7330.  
  7331. This function saves a modified preferences structure. Do NOT change the 
  7332. preferences unless the user really WANTS to!
  7333.  
  7334. Synopsis:
  7335.     
  7336. SetPrefs( pref, size, doit );
  7337.  
  7338. pref:
  7339.     
  7340. (struct Preferences *) Pointer to your modified Preferences structure.
  7341.  
  7342. size:
  7343.     
  7344. (long) The number of bytes you want to change.
  7345.  
  7346. doit:
  7347.     
  7348. (long) Boolean value which if FALSE, changes the preferences, but will not send 
  7349. a NEWPREFS message. If doit is equal to TRUE, the settings will be changed, and 
  7350. a NEWPREFS message will be sent. As long as the user is changing the values, 
  7351. doit should be FALSE, but when the user has finished, set it to TRUE, and all 
  7352. programs will get a NEWPREFS message.
  7353.  
  7354. DisplayBeep()
  7355.  
  7356. This function flashes the screen's colours. Can be used whenever you want to 
  7357. catch the user's attention.
  7358.  
  7359. Synopsis:
  7360.     
  7361. DisplayBeep( screen );
  7362.    
  7363. screen:
  7364.     
  7365. (struct Screen *) Pointer to the screen, which colours you want to flash. If 
  7366. you have not opened a screen yourself (you are using the Workbench Screen), you 
  7367. can find a pointer to that screen in the Window structure: (my_window is a 
  7368. pointer to an opened window) DisplayBeep( my_window->WScreen );
  7369.  
  7370. DoubleClick()
  7371.  
  7372. This function checks if the user double-clicked on one of the mouse buttons. 
  7373. You give the function the current as well as the previous time when the button 
  7374. was pressed, and it will check the preferences and return TRUE if the two 
  7375. button events happened within the time limit.
  7376.  
  7377. Synopsis:
  7378.     
  7379. double = DoubleClick( sec1, mic1, sec2, mic2 );
  7380.  
  7381. double:
  7382.     
  7383. (long) If the two button events happened within the current time limit, the 
  7384. function will return TRUE, else it will return FALSE.
  7385.  
  7386. sec1:
  7387.     
  7388. (long) Time (seconds) when the button was pressed for the first time.
  7389.  
  7390. mic1:
  7391.     
  7392. (long) Time (micros) when the button was pressed for the first time.
  7393.  
  7394. sec2:
  7395.     
  7396. (long) Current time (seconds).
  7397.  
  7398. mic2:
  7399.     
  7400. (long) Current Time (micros).
  7401.  
  7402. CurrentTime()
  7403.  
  7404. This function gives the current time.
  7405.  
  7406. Synopsis:
  7407.     
  7408. CurrentTime( seconds, micros );
  7409.  
  7410. seconds:
  7411.     
  7412. (long *) Pointer to an ULONG variable which will be initialized with the 
  7413. current seconds stamp.
  7414.  
  7415. micros:
  7416.     
  7417. (long *) Pointer to an ULONG variable which will be initialized with the 
  7418. current micros stamp.
  7419.  
  7420. 9.9  EXAMPLES
  7421.  
  7422. Example 1
  7423. This example shows how to allocate, and deallocate memory.
  7424.  
  7425.  
  7426. Example 2
  7427. This example shows how to allocate and deallocate memory with help of the 
  7428. functions AllocRemember(), and FreeRemember().
  7429.  
  7430. Example 3
  7431. This example shows how to get a copy of the preferences.
  7432.  
  7433. Example 4
  7434. This example shows how to handle double mouse button events.
  7435.  
  7436. Example 5
  7437. This example prints out the current time.
  7438.  
  7439.  
  7440.